⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datetime.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
	    date->wYear = wrap(date->wYear, delta, 1752, 9999);
	    date->wDayOfWeek = DATETIME_CalculateDayOfWeek(date->wDay,date->wMonth,date->wYear);
	    break;
	case ONEDIGITMONTH:
	case TWODIGITMONTH:
	case THREECHARMONTH:
	case FULLMONTH:
	    date->wMonth = wrap(date->wMonth, delta, 1, 12);
	    date->wDayOfWeek = DATETIME_CalculateDayOfWeek(date->wDay,date->wMonth,date->wYear);
	    delta = 0;
	    /* fall through */
	case ONEDIGITDAY:
	case TWODIGITDAY:
	case THREECHARDAY:
	case FULLDAY:
	    date->wDay = wrap(date->wDay, delta, 1, MONTHCAL_MonthLength(date->wMonth, date->wYear));
	    date->wDayOfWeek = DATETIME_CalculateDayOfWeek(date->wDay,date->wMonth,date->wYear);
	    break;
	case ONELETTERAMPM:
	case TWOLETTERAMPM:
	    delta *= 12;
	    /* fall through */
	case ONEDIGIT12HOUR:
	case TWODIGIT12HOUR:
	case ONEDIGIT24HOUR:
	case TWODIGIT24HOUR:
	    date->wHour = wrap(date->wHour, delta, 0, 23);
	    break;
	case ONEDIGITMINUTE:
	case TWODIGITMINUTE:
	    date->wMinute = wrap(date->wMinute, delta, 0, 59);
	    break;
	case ONEDIGITSECOND:
	case TWODIGITSECOND:
	    date->wSecond = wrap(date->wSecond, delta, 0, 59);
	    break;
	case FORMATCALLBACK:
	    FIXME ("Not implemented\n");
	    break;
    }

    /* FYI: On 1752/9/14 the calendar changed and England and the
     * American colonies changed to the Gregorian calendar. This change
     * involved having September 14th follow September 2nd. So no date
     * algorithm works before that date.
     */
    if (10000 * date->wYear + 100 * date->wMonth + date->wDay < 17520914) {
	date->wYear = 1752;
    	date->wMonth = 9;
	date->wDay = 14;
	date->wSecond = 0;
	date->wMinute = 0;
	date->wHour = 0;
    }
}


static void
DATETIME_ReturnFieldWidth (DATETIME_INFO *infoPtr, HDC hdc, int count, SHORT *fieldWidthPtr)
{
    /* fields are a fixed width, determined by the largest possible string */
    /* presumably, these widths should be language dependent */
    static const WCHAR fld_d1W[] = { '2', 0 };
    static const WCHAR fld_d2W[] = { '2', '2', 0 };
    static const WCHAR fld_d4W[] = { '2', '2', '2', '2', 0 };
    static const WCHAR fld_am1[] = { 'A', 0 };
    static const WCHAR fld_am2[] = { 'A', 'M', 0 };
    static const WCHAR fld_day[] = { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 };
    static const WCHAR fld_day3[] = { 'W', 'e', 'd', 0 };
    static const WCHAR fld_mon[] = { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 };
    static const WCHAR fld_mon3[] = { 'D', 'e', 'c', 0 };
    int spec;
    WCHAR buffer[80];
    LPCWSTR bufptr;
    SIZE size;

    TRACE ("%d,%d\n", infoPtr->nrFields, count);
    if (count>infoPtr->nrFields || count < 0) {
	WARN ("buffer overrun, have %d want %d\n", infoPtr->nrFields, count);
	return;
    }

    if (!infoPtr->fieldspec) return;

    spec = infoPtr->fieldspec[count];
    if (spec & DT_STRING) {
	int txtlen = infoPtr->buflen[count];

        if (txtlen > 79)
            txtlen = 79;
	memcpy (buffer, infoPtr->textbuf + (spec &~ DT_STRING), txtlen * sizeof(WCHAR));
	buffer[txtlen] = 0;
	bufptr = buffer;
    }
    else {
        switch (spec) {
	    case ONEDIGITDAY:
	    case ONEDIGIT12HOUR:
	    case ONEDIGIT24HOUR:
	    case ONEDIGITSECOND:
	    case ONEDIGITMINUTE:
	    case ONEDIGITMONTH:
	    case ONEDIGITYEAR:
	        /* these seem to use a two byte field */
	    case TWODIGITDAY:
	    case TWODIGIT12HOUR:
	    case TWODIGIT24HOUR:
	    case TWODIGITSECOND:
	    case TWODIGITMINUTE:
	    case TWODIGITMONTH:
	    case TWODIGITYEAR:
	        bufptr = fld_d2W;
	        break;
            case INVALIDFULLYEAR:
	    case FULLYEAR:
	        bufptr = fld_d4W;
	        break;
	    case THREECHARDAY:
	        bufptr = fld_day3;
	        break;
	    case FULLDAY:
	        bufptr = fld_day;
	        break;
	    case THREECHARMONTH:
	        bufptr = fld_mon3;
	        break;
	    case FULLMONTH:
	        bufptr = fld_mon;
	        break;
	    case ONELETTERAMPM:
	        bufptr = fld_am1;
	        break;
	    case TWOLETTERAMPM:
	        bufptr = fld_am2;
	        break;
	    default:
	        bufptr = fld_d1W;
	        break;
        }
    }
    GetTextExtentPoint32W (hdc, bufptr, strlenW(bufptr), &size);
    *fieldWidthPtr = size.cx;
}

static void 
DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc)
{
    int i,prevright;
    RECT *field;
    RECT *rcDraw = &infoPtr->rcDraw;
    RECT *calbutton = &infoPtr->calbutton;
    RECT *checkbox = &infoPtr->checkbox;
    SIZE size;
    COLORREF oldTextColor;
    SHORT fieldWidth = 0;

    /* draw control edge */
    TRACE("\n");

    if (infoPtr->dateValid) {
        HFONT oldFont = SelectObject (hdc, infoPtr->hFont);
        INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
        WCHAR txt[80];

        DATETIME_ReturnTxt (infoPtr, 0, txt, sizeof(txt)/sizeof(txt[0]));
        GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
        rcDraw->bottom = size.cy + 2;

        prevright = checkbox->right = ((infoPtr->dwStyle & DTS_SHOWNONE) ? 18 : 2);

        for (i = 0; i < infoPtr->nrFields; i++) {
            DATETIME_ReturnTxt (infoPtr, i, txt, sizeof(txt)/sizeof(txt[0]));
            GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
            DATETIME_ReturnFieldWidth (infoPtr, hdc, i, &fieldWidth);
            field = &infoPtr->fieldRect[i];
            field->left  = prevright;
            field->right = prevright + fieldWidth;
            field->top   = rcDraw->top;
            field->bottom = rcDraw->bottom;
            prevright = field->right;

            if (infoPtr->dwStyle & WS_DISABLED)
                oldTextColor = SetTextColor (hdc, comctl32_color.clrGrayText);
            else if ((infoPtr->haveFocus) && (i == infoPtr->select)) {
                /* fill if focussed */
                HBRUSH hbr = CreateSolidBrush (comctl32_color.clrActiveCaption);
                FillRect(hdc, field, hbr);
                DeleteObject (hbr);
                oldTextColor = SetTextColor (hdc, comctl32_color.clrWindow);
            }
            else
                oldTextColor = SetTextColor (hdc, comctl32_color.clrWindowText);

            /* draw the date text using the colour set above */
            DrawTextW (hdc, txt, strlenW(txt), field, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
            SetTextColor (hdc, oldTextColor);
        }
        SetBkMode (hdc, oldBkMode);
        SelectObject (hdc, oldFont);
    }

    if (!(infoPtr->dwStyle & DTS_UPDOWN)) {
        DrawFrameControl(hdc, calbutton, DFC_SCROLL,
                         DFCS_SCROLLDOWN | (infoPtr->bCalDepressed ? DFCS_PUSHED : 0) |
                         (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
    }
}


static INT
DATETIME_HitTest (DATETIME_INFO *infoPtr, POINT pt)
{
    int i;

    TRACE ("%d, %d\n", pt.x, pt.y);

    if (PtInRect (&infoPtr->calbutton, pt)) return DTHT_MCPOPUP;
    if (PtInRect (&infoPtr->checkbox, pt)) return DTHT_CHECKBOX;

    for (i=0; i < infoPtr->nrFields; i++) {
        if (PtInRect (&infoPtr->fieldRect[i], pt)) return i;
    }

    return DTHT_NONE;
}


static LRESULT
DATETIME_LButtonDown (DATETIME_INFO *infoPtr, WORD wKey, INT x, INT y)
{
    POINT pt;
    int old, new;

    pt.x = x;
    pt.y = y;
    old = infoPtr->select;
    new = DATETIME_HitTest (infoPtr, pt);

    /* FIXME: might be conditions where we don't want to update infoPtr->select */
    infoPtr->select = new;

    SetFocus(infoPtr->hwndSelf);

    if (infoPtr->select == DTHT_MCPOPUP) {
        RECT rcMonthCal;
        SendMessageW(infoPtr->hMonthCal, MCM_GETMINREQRECT, 0, (LPARAM)&rcMonthCal);

        /* FIXME: button actually is only depressed during dropdown of the */
        /* calendar control and when the mouse is over the button window */
        infoPtr->bCalDepressed = TRUE;

        /* recalculate the position of the monthcal popup */
        if(infoPtr->dwStyle & DTS_RIGHTALIGN)
            infoPtr->monthcal_pos.x = infoPtr->calbutton.left - 
                (rcMonthCal.right - rcMonthCal.left);
        else
            /* FIXME: this should be after the area reserved for the checkbox */
            infoPtr->monthcal_pos.x = infoPtr->rcDraw.left;

        infoPtr->monthcal_pos.y = infoPtr->rcClient.bottom;
        ClientToScreen (infoPtr->hwndSelf, &(infoPtr->monthcal_pos));
        SetWindowPos(infoPtr->hMonthCal, 0, infoPtr->monthcal_pos.x,
            infoPtr->monthcal_pos.y, rcMonthCal.right - rcMonthCal.left,
            rcMonthCal.bottom - rcMonthCal.top, 0);

        if(IsWindowVisible(infoPtr->hMonthCal)) {
            ShowWindow(infoPtr->hMonthCal, SW_HIDE);
        } else {
            SYSTEMTIME *lprgSysTimeArray = &infoPtr->date;
            TRACE("update calendar %04d/%02d/%02d\n", 
            lprgSysTimeArray->wYear, lprgSysTimeArray->wMonth, lprgSysTimeArray->wDay);
            SendMessageW(infoPtr->hMonthCal, MCM_SETCURSEL, 0, (LPARAM)(&infoPtr->date));
            ShowWindow(infoPtr->hMonthCal, SW_SHOW);
        }

        TRACE ("dt:%p mc:%p mc parent:%p, desktop:%p\n",
               infoPtr->hwndSelf, infoPtr->hMonthCal, infoPtr->hwndNotify, GetDesktopWindow ());
        DATETIME_SendSimpleNotify (infoPtr, DTN_DROPDOWN);
    }

    InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);

    return 0;
}


static LRESULT
DATETIME_LButtonUp (DATETIME_INFO *infoPtr, WORD wKey)
{
    if(infoPtr->bCalDepressed) {
        infoPtr->bCalDepressed = FALSE;
        InvalidateRect(infoPtr->hwndSelf, &(infoPtr->calbutton), TRUE);
    }

    return 0;
}


static LRESULT
DATETIME_Paint (DATETIME_INFO *infoPtr, HDC hdc)
{
    if (!hdc) {
	PAINTSTRUCT ps;
        hdc = BeginPaint (infoPtr->hwndSelf, &ps);
        DATETIME_Refresh (infoPtr, hdc);
        EndPaint (infoPtr->hwndSelf, &ps);
    } else {
        DATETIME_Refresh (infoPtr, hdc);
    }
    return 0;
}


static LRESULT
DATETIME_Button_Command (DATETIME_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    if( HIWORD(wParam) == BN_CLICKED) {
        DWORD state = SendMessageW((HWND)lParam, BM_GETCHECK, 0, 0);
        infoPtr->dateValid = (state == BST_CHECKED);
        InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
    }
    return 0;
}
          
        
        
static LRESULT
DATETIME_Command (DATETIME_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
    TRACE("hwndbutton = %p\n", infoPtr->hwndCheckbut);
    if(infoPtr->hwndCheckbut == (HWND)lParam)
        return DATETIME_Button_Command(infoPtr, wParam, lParam);
    return 0;
}


static LRESULT
DATETIME_Enable (DATETIME_INFO *infoPtr, BOOL bEnable)
{
    TRACE("%p %s\n", infoPtr, bEnable ? "TRUE" : "FALSE");
    if (bEnable)
        infoPtr->dwStyle &= ~WS_DISABLED;
    else
        infoPtr->dwStyle |= WS_DISABLED;
    return 0;
}


static LRESULT
DATETIME_EraseBackground (DATETIME_INFO *infoPtr, HDC hdc)
{
    HBRUSH hBrush, hSolidBrush = NULL;
    RECT   rc;

    if (infoPtr->dwStyle & WS_DISABLED)
        hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrBtnFace);
    else
    {
        hBrush = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLOREDIT,
                                      (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
        if (!hBrush)
            hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrWindow);
    }

    GetClientRect (infoPtr->hwndSelf, &rc);

    FillRect (hdc, &rc, hBrush);

    if (hSolidBrush)
        DeleteObject(hSolidBrush);

    return -1;
}


static LRESULT
DATETIME_Notify (DATETIME_INFO *infoPtr, int idCtrl, LPNMHDR lpnmh)
{
    TRACE ("Got notification %x from %p\n", lpnmh->code, lpnmh->hwndFrom);
    TRACE ("info: %p %p %p\n", infoPtr->hwndSelf, infoPtr->hMonthCal, infoPtr->hUpdown);

    if (lpnmh->code == MCN_SELECT) {
        ShowWindow(infoPtr->hMonthCal, SW_HIDE);
        infoPtr->dateValid = TRUE;
        SendMessageW (infoPtr->hMonthCal, MCM_GETCURSEL, 0, (LPARAM)&infoPtr->date);
        TRACE("got from calendar %04d/%02d/%02d day of week %d\n", 
        infoPtr->date.wYear, infoPtr->date.wMonth, infoPtr->date.wDay, infoPtr->date.wDayOfWeek);
        SendMessageW (infoPtr->hwndCheckbut, BM_SETCHECK, BST_CHECKED, 0);
        InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
        DATETIME_SendDateTimeChangeNotify (infoPtr);
    }
    if ((lpnmh->hwndFrom == infoPtr->hUpdown) && (lpnmh->code == UDN_DELTAPOS)) {
        LPNMUPDOWN lpnmud = (LPNMUPDOWN)lpnmh;
        TRACE("Delta pos %d\n", lpnmud->iDelta);
        infoPtr->pendingUpdown = lpnmud->iDelta;
    }
    return 0;
}


static LRESULT
DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode, LPARAM flags)
{
    int fieldNum = infoPtr->select & DTHT_DATEFIELD;
    int wrap = 0;

    if (!(infoPtr->haveFocus)) return 0;
    if ((fieldNum==0) && (infoPtr->select)) return 0;

    if (infoPtr->select & FORMATCALLMASK) {
	FIXME ("Callbacks not implemented yet\n");
    }

    if (vkCode >= '0' && vkCode <= '9') {
        /* this is a somewhat simplified version of what Windows does */
	SYSTEMTIME *date = &infoPtr->date;
	switch (infoPtr->fieldspec[fieldNum]) {
	    case ONEDIGITYEAR:
	    case TWODIGITYEAR:
	        date->wYear = date->wYear - (date->wYear%100) +
	                (date->wYear%10)*10 + (vkCode-'0');
	        date->wDayOfWeek = DATETIME_CalculateDayOfWeek(
	                date->wDay,date->wMonth,date->wYear);
	        DATETIME_SendDateTimeChangeNotify (infoPtr);
	        break;
            case INVALIDFULLYEAR:
	    case FULLYEAR:
	        date->wYear = (date->wYear%1000)*10 + (vkCode-'0');
	        date->wDayOfWeek = DATETIME_CalculateDayOfWeek(
	                date->wDay,date->wMonth,date->wYear);
	        DATETIME_SendDateTimeChangeNotify (infoPtr);
	        break;
	    case ONEDIGITMONTH:
	    case TWODIGITMONTH:
	        if ((date->wMonth%10) > 1 || (vkCode-'0') > 2)
	            date->wMonth = vkCode-'0';
	        else
	            date->wMonth = (date->wMonth%10)*10+vkCode-'0';
	        date->wDayOfWeek = DATETIME_CalculateDayOfWeek(
	                date->wDay,date->wMonth,date->wYear);
	        DATETIME_SendDateTimeChangeNotify (infoPtr);
	        break;
	    case ONEDIGITDAY:
	    case TWODIGITDAY:
	        /* probably better checking here would help */
	        if ((date->wDay%10) >= 3 && (vkCode-'0') > 1)
	            date->wDay = vkCode-'0';
	        else
	            date->wDay = (date->wDay%10)*10+vkCode-'0';
	        date->wDayOfWeek = DATETIME_CalculateDayOfWeek(
	                date->wDay,date->wMonth,date->wYear);
	        DATETIME_SendDateTimeChangeNotify (infoPtr);
	        break;
	    case ONEDIGIT12HOUR:
	    case TWODIGIT12HOUR:
	        if ((date->wHour%10) > 1 || (vkCode-'0') > 2)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -