/* * Windows Calendar * Copyright (c) 1985 by Microsoft Corporation, all rights reserved. * Written by Mark L. Chamberlin, consultant to Microsoft. * ****** calcmd2.c * */ #include "cal.h" #define ATTRDIR 0xC010 /* added for the revised SaveAs dialog */ #include #include /* Get O_RDONLY definition for open call. */ CHAR rgch[256]; /* moved out of FnSaveAs because of 512 byte limit of local variables */ CHAR szFullPathName[120]; INT CheckMarginNums(HWND hWnd); BOOL APIENTRY CallSaveAsDialog () { CHAR szSaveFileSpec [CCHFILESPECMAX] = ""; CHAR szAnsiFileSpec [CCHFILESPECMAX]; extern CHAR szLastDir[]; /* default selection in edit window */ lstrcpy (szSaveFileSpec, OFStruct[IDFILEORIGINAL].szPathName); /* set up the variable fields of the OPENFILENAME struct. (the constant * fields have been sel in CalInit() */ vOFN.lpstrFile = szSaveFileSpec; vOFN.lpstrInitialDir = szLastDir; vOFN.lpstrTitle = vszSaveasCaption; vOFN.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; /* always 0 for SaveAs */ /* All long pointers should be defined immediately before the call. * L.Raman - 2/12/91 */ vOFN.lpstrFilter = vszFilterSpec; vOFN.lpstrCustomFilter = vszCustFilterSpec; vOFN.lpstrDefExt = vszFileExtension + 1; /* point to "CAL" */ if ( GetSaveFileName ((LPOPENFILENAME)&vOFN)) { // on NT, don't do the oemtoansi, just copy the file into new buffer. // OemToAnsi(vOFN.lpstrFile, szAnsiFileSpec); strcpy(szAnsiFileSpec, vOFN.lpstrFile); return FSaveFile (szAnsiFileSpec, FALSE); } return FALSE; } /**************************************************************************** * * INT_PTR FnPageSetup (hwnd, message, wParam, lParam) * * purpose : Dialog function for page setup dialog. Accepts header/footer * formatting instructions and margin lengths. * * params : same as for all dialog functions * * ***************************************************************************/ INT_PTR CALLBACK FnPageSetup ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { int id; WORD2DWORD iSelFirst; WORD2DWORD iSelLast; switch (message) { case WM_INITDIALOG : EnableWindow (GetDlgItem (hwnd, IDOK), TRUE); /* Set the Dialog Items to what they were before. Also handles case * when Page Setup is chosen for the first time. */ for (id=IDCN_EDITHEADER; id < IDCN_EDITHEADER+6; id++) { SendDlgItemMessage(hwnd, id, EM_LIMITTEXT, PT_LEN-1, 0L); SetDlgItemText(hwnd, id, chPageText[id-IDCN_EDITHEADER]); } iSelLast = PT_LEN-1; iSelFirst = 0; MSendMsgEM_GETSEL(GetDlgItem(hwnd, IDCN_EDITHEADER), &iSelFirst, &iSelLast); CalSetFocus (GetDlgItem (hwnd, IDCN_EDITHEADER)); break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: /* Store the changes made only if margins are valid nums. */ id = CheckMarginNums(hwnd); if (id <= 0) /* invalid margins */ { MessageBox(hwnd, vszIncorrectSyntax, vszCalendar, MB_OK | MB_ICONEXCLAMATION); if (id == 0) /* can't guess invalid margin */ return TRUE; /* continue the dialog */ else { CalSetFocus(GetDlgItem (hwnd, -id)); return FALSE; } } /* store the margin values */ for (id = IDCN_EDITHEADER; id <= IDCN_EDITHEADER+6; id++) GetDlgItemText(hwnd, id, chPageText[id-IDCN_EDITHEADER], PT_LEN-1); EndDialog (hwnd, TRUE); break; case IDCANCEL : EndDialog (hwnd, FALSE); break; } return TRUE; } return FALSE; } /* Check valididity of margin values specified. * return TRUE if margins are valid. * * returns -IDCN_EDITMARGINLEFT if Left margin is invalid, * -IDCN_EDITMARGINRIGHT if Right margin is invalid * -IDCN_EDITMARGINTOP if Top margin is invalid * -IDCN_EDITMARGINBOTTOM if Bottom margin is invalid * 0/FALSE if it cannot guess the invalid margin */ INT CheckMarginNums(HWND hWnd) { SHORT n; CHAR *pStr; CHAR szStr[PT_LEN]; UINT Left, Right, Top, Bottom; HDC hPrintDC; UINT xPixInch, yPixInch, xPrintRes, yPrintRes; for (n = IDCN_EDITHEADER+2; n < IDCN_EDITHEADER+6; n++) { GetDlgItemText(hWnd, n, szStr, PT_LEN); pStr = szStr; while (*pStr) if (isdigit(*pStr) || *pStr == szDec[0]) pStr = AnsiNext(pStr); else return (-n); } if (!(hPrintDC = GetPrinterDC())) return FALSE; xPrintRes = GetDeviceCaps(hPrintDC, HORZRES); yPrintRes = GetDeviceCaps(hPrintDC, VERTRES); xPixInch = GetDeviceCaps(hPrintDC, LOGPIXELSX); yPixInch = GetDeviceCaps(hPrintDC, LOGPIXELSY); DeleteDC(hPrintDC); /* margin values have int/float values. Do range check */ GetDlgItemText(hWnd, IDCN_EDITMARGINLEFT, szStr, PT_LEN); Left = atopix(szStr,xPixInch); GetDlgItemText(hWnd, IDCN_EDITMARGINRIGHT, szStr, PT_LEN); Right = atopix(szStr, xPixInch); GetDlgItemText(hWnd, IDCN_EDITMARGINTOP, szStr, PT_LEN); Top = atopix(szStr, yPixInch); GetDlgItemText(hWnd, IDCN_EDITMARGINBOT, szStr, PT_LEN); Bottom = atopix(szStr, yPixInch); /* try to guess the invalid margin */ if (Left >= xPrintRes) return -IDCN_EDITMARGINLEFT; /* Left margin is invalid */ else if (Right >= xPrintRes) return -IDCN_EDITMARGINRIGHT; /* Right margin is invalid */ else if (Top >= yPrintRes) return -IDCN_EDITMARGINTOP; /* Top margin is invalid */ else if (Bottom >= yPrintRes) return -IDCN_EDITMARGINBOT; /* Bottom margin is invalid */ else if (Left >= (xPrintRes-Right)) return FALSE; /* can't guess, return FALSE */ else if (Top >= (yPrintRes-Bottom)) return FALSE; /* can't guess, return FALSE */ return TRUE; } /**** FnDate */ INT_PTR CALLBACK FnDate ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { CHAR szDate [CCHDASHDATE]; INT iErr; switch (message) { case WM_INITDIALOG: /* Remember the window handle of the dialog for AlertBox. */ vhwndDialog = hwnd; SetDlgItemText (hwnd, IDCN_TODATE, ""); return (TRUE); case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: GetDlgItemText (hwnd, IDCN_TODATE, szDate, CCHDASHDATE); if ((iErr = FD3FromDateSz (szDate, &vd3To)) == 0) EndDialog (hwnd, TRUE); else { /* Error in date - put up message box. */ DateTimeAlert(TRUE, iErr); /* line added to fix keyboard hang problem when running under 1.11 */ CalSetFocus (GetDlgItem(hwnd, IDCN_TODATE)); /* Select entire contents of edit control. */ /* 16 July 1989 Clark Cyr */ SendDlgItemMessage(hwnd, IDCN_TODATE, EM_SETSEL, 0, (DWORD)(-1L)); } break; case IDCANCEL: EndDialog (hwnd, FALSE); break; } return (TRUE); } /* Tell Windows we did not process the message. */ return (FALSE); } /**** FnControls */ INT_PTR CALLBACK FnControls ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static BOOL fSound; static UINT cMinEarlyRing; BOOL fOk; switch (message) { case WM_INITDIALOG: /* Remember the window handle of the dialog for AlertBox. */ vhwndDialog = hwnd; CheckDlgButton (hwnd, IDCN_SOUND, fSound = vfSound); SetDlgItemInt (hwnd, IDCN_EARLYRING, cMinEarlyRing = vcMinEarlyRing, FALSE); return (TRUE); case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: cMinEarlyRing = GetDlgItemInt (hwnd, IDCN_EARLYRING, &fOk, FALSE); if (!fOk || cMinEarlyRing > 10) { /* The value didn't parse or it's not within range. Put up an error message. */ AlertBox (vszBadEarlyRing, (CHAR *)NULL, MB_APPLMODAL | MB_OK | MB_ICONASTERISK); /* Don't end the dialog - they will have to enter a proper time or cancel. */ /* line added to fix keyboard hanging problem in ver 1.11 */ CalSetFocus (GetDlgItem( hwnd, IDCN_EARLYRING)); break; } /* Assign the new values. */ vfSound = fSound; vcMinEarlyRing = cMinEarlyRing; EndDialog (hwnd, TRUE); break; case IDCANCEL: EndDialog (hwnd, FALSE); break; case IDCN_SOUND: CheckDlgButton (hwnd, IDCN_SOUND, !IsDlgButtonChecked (hwnd, IDCN_SOUND)); fSound = !fSound; break; } return (TRUE); } /* Tell Windows we did not process the message. */ return (FALSE); } /**** FnSpecialTime */ INT_PTR CALLBACK FnSpecialTime ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static INT idcheck; CHAR szTime [CCHTIMESZ]; register CHAR *szError; register TM tm; INT iErr; switch (message) { case WM_INITDIALOG: /* Remember the window handle of the dialog for AlertBox. */ vhwndDialog = hwnd; /* If the currently selected appointment is not for a regular time, put the time into the edit control as the default. This makes it easy for the user to delete the special time. */ if ((tm = vtld [vlnCur].tm) % vcMinInterval != 0) { GetTimeSz (tm, szTime); SetDlgItemText (hwnd, IDCN_EDIT, szTime); } /* Enable or disable the Insert and Delete buttons. */ CheckButtonEnable (hwnd, IDCN_INSERT, EN_CHANGE); CheckButtonEnable (hwnd, IDCN_DELETE, EN_CHANGE); /* Check if the display is in 24Hr format; If so, disable the * AM/PM radio buttons; * Fix for Bug #5447 --SANKAR-- 10-19-89; */ if(vfHour24) { EnableWindow(GetDlgItem(hwnd, IDCN_AM), FALSE); EnableWindow(GetDlgItem(hwnd, IDCN_PM), FALSE); } else CheckRadioButton (hwnd, IDCN_AM, IDCN_PM, viAMorPM); return (TRUE); case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDCN_EDIT: CheckButtonEnable (hwnd, IDCN_INSERT, EN_CHANGE); //- FnSpecialTime: Changed GetParam to EN_CHANGE. //- Not sure why the old one ever worked. //- GET_WM_COMMAND_ID(wParam, lParam)); CheckButtonEnable (hwnd, IDCN_DELETE, EN_CHANGE); //- FnSpecialTime: Changed GetParam to EN_CHANGE. //- GET_WM_COMMAND_ID(wParam, lParam)); break; case IDCANCEL: EndDialog (hwnd, FALSE); break; case IDCN_AM: case IDCN_PM: viAMorPM = GET_WM_COMMAND_ID(wParam, lParam); CheckRadioButton (hwnd, IDCN_AM, IDCN_PM, viAMorPM); break; case IDOK: case IDCN_INSERT: vfInsert = TRUE; szError = vszTimeAlreadyInUse; goto InsDel; case IDCN_DELETE: vfInsert = FALSE; szError = vszNoSuchTime; InsDel: GetDlgItemText (hwnd, IDCN_EDIT, szTime, CCHTIMESZ); if ((iErr = FGetTmFromTimeSz (szTime, &vtmSpecial)) < 0) { /* Error in time - put up message box. */ DateTimeAlert(FALSE, iErr); /* Don't end the dialog - they will have to enter a proper time or cancel. */ CalSetFocus (GetDlgItem (hwnd, IDCN_EDIT)); break; } /* If we are in 24Hr format, then we should not allow * the AM/PM radiobuttons to override; * Fix for Bug #5447 --SANKAR-- 10-19-89 */ if(!vfHour24) { /* AM or PM value on radiobutton overrides text text in edit window */ if (vtmSpecial < TWELVEHOURS) { if (viAMorPM == IDCN_PM) vtmSpecial += TWELVEHOURS; } else if (vtmSpecial > TWELVEHOURS) { if (viAMorPM == IDCN_AM) vtmSpecial -= TWELVEHOURS; } } /* Don't allow a regular time to be inserted or deleted. Note that it's possible for the special time bit for a regular time to be set, but it still can't be deleted. For example, while the interval in 60, insert a special time of 8:30. Then switch the interval to 30. While the interval is 30 (or 15), the 8:30 time cannot be deleted. */ if (vtmSpecial % vcMinInterval == 0) { /* Not a special time. */ AlertBox (vszNotSpecialTime, (CHAR *)NULL, MB_APPLMODAL | MB_OK | MB_ICONASTERISK); break; } /* Don't allow insert if time already in tqr. Don't allow delete if time not in tqr. OK to use bitwise xor since TRUE == 1 and FALSE == 0. */ if (!(FSearchTqr (vtmSpecial) ^ vfInsert)) { AlertBox (szError, (CHAR *)NULL, MB_APPLMODAL | MB_OK| MB_ICONASTERISK); break; } EndDialog (hwnd, TRUE); break; } return (TRUE); } /* Tell Windows we did not process the message. */ return (FALSE); } /**** FnDaySettings */ INT_PTR CALLBACK FnDaySettings ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static INT idcnInterval; static INT idcnHourFormat; INT vfHour24New; INT iErr; CHAR szTime [CCHTIMESZ]; switch (message) { case WM_INITDIALOG: /* Remember the window handle of the dialog for AlertBox. */ vhwndDialog = hwnd; CheckRadioButton (hwnd, IDCN_HOUR12, IDCN_HOUR24, idcnHourFormat = IDCN_HOUR12 + vfHour24); GetTimeSz (vtmStart, szTime); SetDlgItemText (hwnd, IDCN_STARTINGTIME, szTime); /* We want the current setting of interval to be checked, and we want the interval group of radio buttons to have the focus. It doesn't work to call CheckRadioButton here and then let Windows set the focus to the first TABGRP in the dialog box, since when it sets the focus, it also sends us a message to check the first button in the group (so we would always get 15 checked instead of the current setting). So we do our own SetFocus to the interval button we want to check. We then return FALSE to tell Windows that we have done our own SetFocus. */ CalSetFocus (GetDlgItem (hwnd, idcnInterval = IDCN_MIN15 + vmdInterval)); return (FALSE); case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: GetDlgItemText (hwnd, IDCN_STARTINGTIME, szTime, CCHTIMESZ); /* Note - FGetTmFromTimeSz does not affect vtmStart if it returns FALSE (i.e., if it detects an error in the time string). */ if ((iErr = FGetTmFromTimeSz (szTime, &vtmStart)) < 0) { /* Error in time - put up message box. */ DateTimeAlert(FALSE, iErr); /* Don't end the dialog - they will have to enter a proper time or cancel. */ /* line added to fix keyboard hang problem while running under 3.0 ver 1.11 */ CalSetFocus (GetDlgItem (hwnd, IDCN_STARTINGTIME)); break; } vfHour24New = idcnHourFormat - IDCN_HOUR12; if (vfHour24 != vfHour24New) { vfHour24 = vfHour24New; InitTimeDate(vhInstance, vfHour24 ? GTS_24HOUR : GTS_12HOUR); } switch (vmdInterval = idcnInterval - IDCN_MIN15) { case MDINTERVAL15: vcMinInterval = 15; break; case MDINTERVAL30: vcMinInterval = 30; break; case MDINTERVAL60: vcMinInterval = 60; break; } EndDialog (hwnd, TRUE); break; case IDCANCEL: EndDialog (hwnd, FALSE); break; case IDCN_MIN15: case IDCN_MIN30: case IDCN_MIN60: CheckRadioButton (hwnd, IDCN_MIN15, IDCN_MIN60, idcnInterval = GET_WM_COMMAND_ID(wParam, lParam)); break; case IDCN_HOUR12: case IDCN_HOUR24: CheckRadioButton (hwnd, IDCN_HOUR12, IDCN_HOUR24, idcnHourFormat = GET_WM_COMMAND_ID(wParam, lParam)); break; } return (TRUE); } /* Tell Windows we did not process the message. */ return (FALSE); } /**************************************************************** * * INT_PTR FAR PASCAL FnMarkDay ( hwnd, message, wParam, lParam) * * purpose : puts up Options Mark dialog box and receives the * marks that are to be put up against the current day. * ***************************************************************/ INT_PTR APIENTRY FnMarkDay ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { BOOL checkbutton = FALSE; switch (message) { case WM_INITDIALOG: /* check buttons corresp. to active marks on selected day */ CheckDlgButton( hwnd, IDCN_MARKBOX, (viMarkSymbol & MARK_BOX)); CheckDlgButton( hwnd, IDCN_MARKPARENTHESES, (viMarkSymbol & MARK_PARENTHESES)); CheckDlgButton( hwnd, IDCN_MARKCIRCLE, (viMarkSymbol & MARK_CIRCLE)); CheckDlgButton( hwnd, IDCN_MARKCROSS, (viMarkSymbol & MARK_CROSS)); CheckDlgButton( hwnd, IDCN_MARKUNDERSCORE, (viMarkSymbol & MARK_UNDERSCORE)); CalSetFocus (GetDlgItem (hwnd, IDCN_MARKBOX)); return FALSE; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: viMarkSymbol = 0; /* clear existing bit pattern. This is done so that only the marks specified in dialog will appear on current day */ /* bits corresp. to selected mark symbols are set in MarkSymbol */ if (IsDlgButtonChecked(hwnd, IDCN_MARKBOX)) viMarkSymbol |= MARK_BOX; if (IsDlgButtonChecked(hwnd, IDCN_MARKPARENTHESES)) viMarkSymbol |= MARK_PARENTHESES; if (IsDlgButtonChecked(hwnd, IDCN_MARKCIRCLE)) viMarkSymbol |= MARK_CIRCLE; if (IsDlgButtonChecked(hwnd, IDCN_MARKCROSS)) viMarkSymbol |= MARK_CROSS; if (IsDlgButtonChecked(hwnd, IDCN_MARKUNDERSCORE)) viMarkSymbol |= MARK_UNDERSCORE; EndDialog (hwnd, TRUE); break; case IDCANCEL: EndDialog (hwnd, FALSE); break; default : return FALSE; } /* switch wParam */ break; default : return FALSE; } /* switch message */ return TRUE; } /* FnMark */ /**** AlertBox */ INT APIENTRY AlertBox ( CHAR *szText1, CHAR *szText2, UINT wStyle) { CHAR szMessage [160+128]; register CHAR *pch; register HWND hwnd; MergeStrings(szText1, szText2, szMessage); MessageBeep (wStyle); /* The parent window is the active dialog if there is one. If no active dialog, the parent window is Calendar's tiled window. */ if ((hwnd = vhwndDialog) == NULL) hwnd = vhwnd0; return (MessageBox (hwnd, szMessage, vszCalendar, wStyle)); } /**** Scan sz1 for merge spec. If found, insert string sz2 at that point. Then append rest of sz1 NOTE! Merge spec guaranteed to be two chars. returns TRUE if it does a merge, false otherwise. */ BOOL APIENTRY MergeStrings( CHAR *szSrc, CHAR *szMerge, CHAR *szDst) { register CHAR *pchSrc; register CHAR *pchDst; pchSrc = szSrc; pchDst = szDst; #ifdef DBCS /* Find merge spec if there is one. */ //- Merge Bytes: Changed to string to avoid word boundry crossing. while (*pchSrc != *vszMergeStr || *(pchSrc + 1) != *(vszMergeStr + 1)) { if( IsDBCSLeadByte( *pchSrc ) ) *pchDst++ = *pchSrc++; *pchDst++ = *pchSrc; /* If we reach end of string before merge spec, just return. */ if(!*pchSrc++) return FALSE; } #else /* Find merge spec if there is one. */ //- Merge Bytes: Changed to string to avoid word boundry crossing. while (*pchSrc != *vszMergeStr || *(pchSrc + 1) != *(vszMergeStr + 1)) { *pchDst++ = *pchSrc; /* If we reach end of string before merge spec, just return. */ if (!*pchSrc++) return FALSE; } #endif /* If merge spec found, insert sz2 there. (check for null merge string */ if (szMerge) while (*szMerge) *pchDst++ = *szMerge++; /* Jump over merge spec */ pchSrc++,pchSrc++; /* Now append rest of Src String */ while (*pchDst++ = *pchSrc++); return TRUE; } /**** If sz does not have extension, append ".TXT" */ VOID APIENTRY AddDefExt (LPSTR sz) { LPSTR pch1; register INT ch; pch1 = sz + lstrlen(sz); while ((ch = *pch1) != '.' && ch != '\\' && ch != ':' && pch1 > sz) pch1 = AnsiPrev(sz, pch1); if (*pch1 != '.') lstrcat(sz, vrgsz[IDS_FILEEXTENSION]); } /**** CheckButtonEnable - Enable specified button if edit field not null, disable the button if the edit field is null. */ VOID APIENTRY CheckButtonEnable ( HWND hwnd, INT idButton, WORD message) { if (message == EN_CHANGE) { EnableWindow (GetDlgItem (hwnd, idButton), (BOOL)(SendMessage (GetDlgItem (hwnd, IDCN_EDIT), WM_GETTEXTLENGTH, 0, 0L))); } } /* FCheckSave - if the calendar is dirty see if the user wants to Save the the changes. */ BOOL APIENTRY FCheckSave (BOOL fSysModal) { /* Force current edits to be recorded right away since this may cause the file to be dirty. */ RecordEdits (); if (vfDirty) { /* if file has been opened as read only, warn user and return */ if (vfOpenFileReadOnly) { AlertBox (vszFileReadOnly, (CHAR *)NULL, MB_APPLMODAL|MB_OK| MB_ICONEXCLAMATION); /* Force the Save As dialog letting user save under a * different name, thus not losing changes. */ CallSaveAsDialog(); return (TRUE); } switch (AlertBox (vszSaveChanges, vszFileSpec, (fSysModal ? MB_SYSTEMMODAL : MB_APPLMODAL) | MB_YESNOCANCEL | MB_ICONEXCLAMATION)) { case IDYES: if (vfOriginalFile) return (FSaveFile (vszFileSpec, TRUE)); else return CallSaveAsDialog(); case IDCANCEL: return (FALSE); /* The IDNO case falls through to return TRUE. */ } } return (TRUE); } /**** RecordEdits - if the notes or the appointment description edit control has the focus, record the contents of the edit control without changing the focus. */ VOID APIENTRY RecordEdits () { register HWND hwndFocus; if ((hwndFocus = GetFocus ()) == vhwnd2C) StoreNotes (); else if (hwndFocus == vhwnd3) StoreQd (); } /**** Display error when user types date or time in wrong Format */ VOID APIENTRY DateTimeAlert( BOOL fDate, INT iErr) { CHAR sz[256]; CHAR *pch1; CHAR *pch2 = 0; DOSDATE dd; switch (iErr) { /* Range error only occurs for dates */ case PD_ERRRANGE: pch1 = vrgsz[IDS_DATERANGE]; break; case PD_ERRSUBRANGE: pch1 = vrgsz[fDate ? IDS_DATESUBRANGE : IDS_TIMESUBRANGE]; break; case PD_ERRFORMAT: pch1 = fDate ? vrgsz[IDS_BADDATE] : vrgsz[IDS_BADTIME]; pch2 = sz; if (fDate) { dd.month = vd3Sel.wMonth + 1; dd.day = vd3Sel.wDay + 1; dd.year = vd3Sel.wYear + 1980; GetDateString(&dd, pch2, GDS_SHORT); } else GetTimeSz(vftCur.tm, pch2); break; } AlertBox (pch1, pch2, MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION); }