📄 datetime.c
字号:
date->wHour = vkCode-'0';
else
date->wHour = (date->wHour%10)*10+vkCode-'0';
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGIT24HOUR:
case TWODIGIT24HOUR:
if ((date->wHour%10) > 2)
date->wHour = vkCode-'0';
else if ((date->wHour%10) == 2 && (vkCode-'0') > 3)
date->wHour = vkCode-'0';
else
date->wHour = (date->wHour%10)*10+vkCode-'0';
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGITMINUTE:
case TWODIGITMINUTE:
if ((date->wMinute%10) > 5)
date->wMinute = vkCode-'0';
else
date->wMinute = (date->wMinute%10)*10+vkCode-'0';
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case ONEDIGITSECOND:
case TWODIGITSECOND:
if ((date->wSecond%10) > 5)
date->wSecond = vkCode-'0';
else
date->wSecond = (date->wSecond%10)*10+vkCode-'0';
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
}
}
switch (vkCode) {
case VK_ADD:
case VK_UP:
DATETIME_IncreaseField (infoPtr, fieldNum, 1);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_SUBTRACT:
case VK_DOWN:
DATETIME_IncreaseField (infoPtr, fieldNum, -1);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_HOME:
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MIN);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_END:
DATETIME_IncreaseField (infoPtr, fieldNum, INT_MAX);
DATETIME_SendDateTimeChangeNotify (infoPtr);
break;
case VK_LEFT:
do {
if (infoPtr->select == 0) {
infoPtr->select = infoPtr->nrFields - 1;
wrap++;
} else {
infoPtr->select--;
}
} while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2));
break;
case VK_RIGHT:
do {
infoPtr->select++;
if (infoPtr->select==infoPtr->nrFields) {
infoPtr->select = 0;
wrap++;
}
} while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2));
break;
}
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT
DATETIME_VScroll (DATETIME_INFO *infoPtr, WORD wScroll)
{
int fieldNum = infoPtr->select & DTHT_DATEFIELD;
if ((SHORT)LOWORD(wScroll) != SB_THUMBPOSITION) return 0;
if (!(infoPtr->haveFocus)) return 0;
if ((fieldNum==0) && (infoPtr->select)) return 0;
if (infoPtr->pendingUpdown >= 0) {
DATETIME_IncreaseField (infoPtr, fieldNum, 1);
DATETIME_SendDateTimeChangeNotify (infoPtr);
}
else {
DATETIME_IncreaseField (infoPtr, fieldNum, -1);
DATETIME_SendDateTimeChangeNotify (infoPtr);
}
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT
DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus)
{
TRACE("lost focus to %p\n", lostFocus);
if (infoPtr->haveFocus) {
DATETIME_SendSimpleNotify (infoPtr, NM_KILLFOCUS);
infoPtr->haveFocus = 0;
}
InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT
DATETIME_NCCreate (HWND hwnd, LPCREATESTRUCTW lpcs)
{
DWORD dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
/* force control to have client edge */
dwExStyle |= WS_EX_CLIENTEDGE;
SetWindowLongW(hwnd, GWL_EXSTYLE, dwExStyle);
return DefWindowProcW(hwnd, WM_NCCREATE, 0, (LPARAM)lpcs);
}
static LRESULT
DATETIME_SetFocus (DATETIME_INFO *infoPtr, HWND lostFocus)
{
TRACE("got focus from %p\n", lostFocus);
if (infoPtr->haveFocus == 0) {
DATETIME_SendSimpleNotify (infoPtr, NM_SETFOCUS);
infoPtr->haveFocus = DTHT_GOTFOCUS;
}
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return 0;
}
static BOOL
DATETIME_SendDateTimeChangeNotify (DATETIME_INFO *infoPtr)
{
NMDATETIMECHANGE dtdtc;
dtdtc.nmhdr.hwndFrom = infoPtr->hwndSelf;
dtdtc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
dtdtc.nmhdr.code = DTN_DATETIMECHANGE;
dtdtc.dwFlags = (infoPtr->dwStyle & DTS_SHOWNONE) ? GDT_NONE : GDT_VALID;
MONTHCAL_CopyTime (&infoPtr->date, &dtdtc.st);
return (BOOL) SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM)dtdtc.nmhdr.idFrom, (LPARAM)&dtdtc);
}
static BOOL
DATETIME_SendSimpleNotify (DATETIME_INFO *infoPtr, UINT code)
{
NMHDR nmhdr;
TRACE("%x\n", code);
nmhdr.hwndFrom = infoPtr->hwndSelf;
nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
nmhdr.code = code;
return (BOOL) SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
}
static LRESULT
DATETIME_Size (DATETIME_INFO *infoPtr, WORD flags, INT width, INT height)
{
/* set size */
infoPtr->rcClient.bottom = height;
infoPtr->rcClient.right = width;
TRACE("Height=%d, Width=%d\n", infoPtr->rcClient.bottom, infoPtr->rcClient.right);
infoPtr->rcDraw = infoPtr->rcClient;
if (infoPtr->dwStyle & DTS_UPDOWN) {
SetWindowPos(infoPtr->hUpdown, NULL,
infoPtr->rcClient.right-14, 0,
15, infoPtr->rcClient.bottom - infoPtr->rcClient.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
else {
/* set the size of the button that drops the calendar down */
/* FIXME: account for style that allows button on left side */
infoPtr->calbutton.top = infoPtr->rcDraw.top;
infoPtr->calbutton.bottom= infoPtr->rcDraw.bottom;
infoPtr->calbutton.left = infoPtr->rcDraw.right-15;
infoPtr->calbutton.right = infoPtr->rcDraw.right;
}
/* set enable/disable button size for show none style being enabled */
/* FIXME: these dimensions are completely incorrect */
infoPtr->checkbox.top = infoPtr->rcDraw.top;
infoPtr->checkbox.bottom = infoPtr->rcDraw.bottom;
infoPtr->checkbox.left = infoPtr->rcDraw.left;
infoPtr->checkbox.right = infoPtr->rcDraw.left + 10;
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return 0;
}
static LRESULT
DATETIME_StyleChanged(DATETIME_INFO *infoPtr, WPARAM wStyleType, LPSTYLESTRUCT lpss)
{
static const WCHAR buttonW[] = { 'b', 'u', 't', 't', 'o', 'n', 0 };
TRACE("(styletype=%x, styleOld=0x%08x, styleNew=0x%08x)\n",
wStyleType, lpss->styleOld, lpss->styleNew);
if (wStyleType != GWL_STYLE) return 0;
infoPtr->dwStyle = lpss->styleNew;
if ( !(lpss->styleOld & DTS_SHOWNONE) && (lpss->styleNew & DTS_SHOWNONE) ) {
infoPtr->hwndCheckbut = CreateWindowExW (0, buttonW, 0, WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
2, 2, 13, 13, infoPtr->hwndSelf, 0,
(HINSTANCE)GetWindowLongPtrW (infoPtr->hwndSelf, GWLP_HINSTANCE), 0);
SendMessageW (infoPtr->hwndCheckbut, BM_SETCHECK, 1, 0);
}
if ( (lpss->styleOld & DTS_SHOWNONE) && !(lpss->styleNew & DTS_SHOWNONE) ) {
DestroyWindow(infoPtr->hwndCheckbut);
infoPtr->hwndCheckbut = 0;
}
if ( !(lpss->styleOld & DTS_UPDOWN) && (lpss->styleNew & DTS_UPDOWN) ) {
infoPtr->hUpdown = CreateUpDownControl (WS_CHILD | WS_BORDER | WS_VISIBLE, 120, 1, 20, 20,
infoPtr->hwndSelf, 1, 0, 0, UD_MAXVAL, UD_MINVAL, 0);
}
if ( (lpss->styleOld & DTS_UPDOWN) && !(lpss->styleNew & DTS_UPDOWN) ) {
DestroyWindow(infoPtr->hUpdown);
infoPtr->hUpdown = 0;
}
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT
DATETIME_SetFont (DATETIME_INFO *infoPtr, HFONT font, BOOL repaint)
{
infoPtr->hFont = font;
if (repaint) InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT
DATETIME_Create (HWND hwnd, LPCREATESTRUCTW lpcs)
{
static const WCHAR SysMonthCal32W[] = { 'S', 'y', 's', 'M', 'o', 'n', 't', 'h', 'C', 'a', 'l', '3', '2', 0 };
DATETIME_INFO *infoPtr = (DATETIME_INFO *)Alloc (sizeof(DATETIME_INFO));
STYLESTRUCT ss = { 0, lpcs->style };
if (!infoPtr) return -1;
infoPtr->hwndSelf = hwnd;
infoPtr->dwStyle = lpcs->style;
infoPtr->nrFieldsAllocated = 32;
infoPtr->fieldspec = (int *) Alloc (infoPtr->nrFieldsAllocated * sizeof(int));
infoPtr->fieldRect = (RECT *) Alloc (infoPtr->nrFieldsAllocated * sizeof(RECT));
infoPtr->buflen = (int *) Alloc (infoPtr->nrFieldsAllocated * sizeof(int));
infoPtr->hwndNotify = lpcs->hwndParent;
infoPtr->select = -1; /* initially, nothing is selected */
DATETIME_StyleChanged(infoPtr, GWL_STYLE, &ss);
DATETIME_SetFormatW (infoPtr, 0);
/* create the monthcal control */
infoPtr->hMonthCal = CreateWindowExW (0, SysMonthCal32W, 0, WS_BORDER | WS_POPUP | WS_CLIPSIBLINGS,
0, 0, 0, 0, infoPtr->hwndSelf, 0, 0, 0);
/* initialize info structure */
GetLocalTime (&infoPtr->date);
infoPtr->dateValid = TRUE;
infoPtr->hFont = GetStockObject(DEFAULT_GUI_FONT);
SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
return 0;
}
static LRESULT
DATETIME_Destroy (DATETIME_INFO *infoPtr)
{
if (infoPtr->hwndCheckbut)
DestroyWindow(infoPtr->hwndCheckbut);
if (infoPtr->hUpdown)
DestroyWindow(infoPtr->hUpdown);
if (infoPtr->hMonthCal)
DestroyWindow(infoPtr->hMonthCal);
SetWindowLongPtrW( infoPtr->hwndSelf, 0, 0 ); /* clear infoPtr */
Free (infoPtr);
return 0;
}
static LRESULT WINAPI
DATETIME_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DATETIME_INFO *infoPtr = ((DATETIME_INFO *)GetWindowLongPtrW (hwnd, 0));
LRESULT ret;
TRACE ("%x, %x, %lx\n", uMsg, wParam, lParam);
if (!infoPtr && (uMsg != WM_CREATE) && (uMsg != WM_NCCREATE))
return DefWindowProcW( hwnd, uMsg, wParam, lParam );
switch (uMsg) {
case DTM_GETSYSTEMTIME:
return DATETIME_GetSystemTime (infoPtr, (SYSTEMTIME *) lParam);
case DTM_SETSYSTEMTIME:
return DATETIME_SetSystemTime (infoPtr, wParam, (SYSTEMTIME *) lParam);
case DTM_GETRANGE:
ret = SendMessageW (infoPtr->hMonthCal, MCM_GETRANGE, wParam, lParam);
return ret ? ret : 1; /* bug emulation */
case DTM_SETRANGE:
return SendMessageW (infoPtr->hMonthCal, MCM_SETRANGE, wParam, lParam);
case DTM_SETFORMATA:
return DATETIME_SetFormatA (infoPtr, (LPCSTR)lParam);
case DTM_SETFORMATW:
return DATETIME_SetFormatW (infoPtr, (LPCWSTR)lParam);
case DTM_GETMONTHCAL:
return (LRESULT)infoPtr->hMonthCal;
case DTM_SETMCCOLOR:
return SendMessageW (infoPtr->hMonthCal, MCM_SETCOLOR, wParam, lParam);
case DTM_GETMCCOLOR:
return SendMessageW (infoPtr->hMonthCal, MCM_GETCOLOR, wParam, 0);
case DTM_SETMCFONT:
return SendMessageW (infoPtr->hMonthCal, WM_SETFONT, wParam, lParam);
case DTM_GETMCFONT:
return SendMessageW (infoPtr->hMonthCal, WM_GETFONT, wParam, lParam);
case WM_NOTIFY:
return DATETIME_Notify (infoPtr, (int)wParam, (LPNMHDR)lParam);
case WM_ENABLE:
return DATETIME_Enable (infoPtr, (BOOL)wParam);
case WM_ERASEBKGND:
return DATETIME_EraseBackground (infoPtr, (HDC)wParam);
case WM_GETDLGCODE:
return DLGC_WANTARROWS | DLGC_WANTCHARS;
case WM_PRINTCLIENT:
case WM_PAINT:
return DATETIME_Paint (infoPtr, (HDC)wParam);
case WM_KEYDOWN:
return DATETIME_KeyDown (infoPtr, wParam, lParam);
case WM_KILLFOCUS:
return DATETIME_KillFocus (infoPtr, (HWND)wParam);
case WM_NCCREATE:
return DATETIME_NCCreate (hwnd, (LPCREATESTRUCTW)lParam);
case WM_SETFOCUS:
return DATETIME_SetFocus (infoPtr, (HWND)wParam);
case WM_SIZE:
return DATETIME_Size (infoPtr, wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
case WM_LBUTTONDOWN:
return DATETIME_LButtonDown (infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
case WM_LBUTTONUP:
return DATETIME_LButtonUp (infoPtr, (WORD)wParam);
case WM_VSCROLL:
return DATETIME_VScroll (infoPtr, (WORD)wParam);
case WM_CREATE:
return DATETIME_Create (hwnd, (LPCREATESTRUCTW)lParam);
case WM_DESTROY:
return DATETIME_Destroy (infoPtr);
case WM_COMMAND:
return DATETIME_Command (infoPtr, wParam, lParam);
case WM_STYLECHANGED:
return DATETIME_StyleChanged(infoPtr, wParam, (LPSTYLESTRUCT)lParam);
case WM_SETFONT:
return DATETIME_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
case WM_GETFONT:
return (LRESULT) infoPtr->hFont;
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
DATETIME_Register (void)
{
WNDCLASSW wndClass;
ZeroMemory (&wndClass, sizeof(WNDCLASSW));
wndClass.style = CS_GLOBALCLASS;
wndClass.lpfnWndProc = DATETIME_WindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = sizeof(DATETIME_INFO *);
wndClass.hCursor = LoadCursorW (0, (LPCWSTR)IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.lpszClassName = DATETIMEPICK_CLASSW;
RegisterClassW (&wndClass);
}
void
DATETIME_Unregister (void)
{
UnregisterClassW (DATETIMEPICK_CLASSW, NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -