Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

804 lines
20 KiB

  1. /*++
  2. Copyright (c) 1994-1998, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. calendar.c
  5. Abstract:
  6. This module implements the calendar control for the Date/Time applet.
  7. Revision History:
  8. --*/
  9. //
  10. // Include Files.
  11. //
  12. #include "timedate.h"
  13. #include "rc.h"
  14. //
  15. // Constant Declarations.
  16. //
  17. #define DEF_FIRST_WEEKDAY (6)
  18. #define cBorderX 5
  19. #define cBorderY 3
  20. #define cBorderSelect 1
  21. #define IS_FE_LANGUAGE(p) (((p) == LANG_CHINESE) || \
  22. ((p) == LANG_JAPANESE) || \
  23. ((p) == LANG_KOREAN))
  24. //
  25. // Typedef Declarations.
  26. //
  27. //
  28. // Struture for global data.
  29. //
  30. typedef struct _CALINFO
  31. {
  32. HWND hwnd; // the hwnd
  33. HFONT hfontCal; // the font to use
  34. BOOL fFocus; // do we have the focus
  35. int cxBlank; // size of a blank
  36. int cxChar; // the width of digits
  37. int cyChar; // the height of digits
  38. } CALINFO, *PCALINFO;
  39. ////////////////////////////////////////////////////////////////////////////
  40. //
  41. // GetFirstDayOfAnyWeek
  42. //
  43. // For this function ONLY:
  44. // 0 = Monday
  45. // 6 = Sunday
  46. //
  47. ////////////////////////////////////////////////////////////////////////////
  48. int GetFirstDayOfAnyWeek()
  49. {
  50. static int iDay = -1;
  51. if (iDay < 0)
  52. {
  53. TCHAR ch[2] = { 0 };
  54. *ch = TEXT('0') + DEF_FIRST_WEEKDAY;
  55. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, ch, 2);
  56. iDay = ( ((*ch >= TEXT('0')) && (*ch <= TEXT('6')))
  57. ? ((int)*ch - TEXT('0'))
  58. : DEF_FIRST_WEEKDAY );
  59. }
  60. return (iDay);
  61. }
  62. ////////////////////////////////////////////////////////////////////////////
  63. //
  64. // GetLocalWeekday
  65. //
  66. ////////////////////////////////////////////////////////////////////////////
  67. int GetLocalWeekday()
  68. {
  69. //
  70. // Convert local first day to 0==sunday and subtract from today.
  71. //
  72. return ((wDateTime[WEEKDAY] + 7 - ((GetFirstDayOfAnyWeek() + 1) % 7)) % 7);
  73. }
  74. void DetermineDayOfWeek()
  75. {
  76. FILETIME FileTime;
  77. SYSTEMTIME SystemTime;
  78. SystemTime.wHour = wDateTime[HOUR];
  79. SystemTime.wMinute = wDateTime[MINUTE];
  80. SystemTime.wSecond = wDateTime[SECOND];
  81. SystemTime.wMilliseconds = 0;
  82. SystemTime.wMonth = wDateTime[MONTH];
  83. SystemTime.wDay = wDateTime[DAY];
  84. SystemTime.wYear = wDateTime[YEAR];
  85. SystemTimeToFileTime(&SystemTime, &FileTime);
  86. FileTimeToSystemTime(&FileTime, &SystemTime);
  87. wDateTime[WEEKDAY] = SystemTime.wDayOfWeek;
  88. }
  89. ////////////////////////////////////////////////////////////////////////////
  90. //
  91. // GetFirstDayOfTheMonth
  92. //
  93. ////////////////////////////////////////////////////////////////////////////
  94. int GetFirstDayOfTheMonth()
  95. {
  96. DetermineDayOfWeek();
  97. return ((GetLocalWeekday() + 8 - (wDateTime[DAY] % 7)) % 7);
  98. }
  99. ////////////////////////////////////////////////////////////////////////////
  100. //
  101. // GetDaysOfTheMonth
  102. //
  103. ////////////////////////////////////////////////////////////////////////////
  104. int GetDaysOfTheMonth(
  105. int iMonth)
  106. {
  107. int cDays;
  108. int nYear;
  109. //
  110. // Calculate the number of days in the current month -
  111. // add one if this is a leap year and the month is February.
  112. //
  113. if (iMonth <= 7)
  114. {
  115. cDays = 30 + (iMonth % 2);
  116. }
  117. else
  118. {
  119. cDays = 31 - (iMonth % 2);
  120. }
  121. if (iMonth == 2)
  122. {
  123. cDays = 28;
  124. nYear = wDateTime[YEAR];
  125. if ((nYear % 4 == 0) && ((nYear % 100 != 0) || (nYear % 400 == 0)))
  126. {
  127. cDays++;
  128. }
  129. }
  130. return (cDays);
  131. }
  132. ////////////////////////////////////////////////////////////////////////////
  133. //
  134. // AdjustDeltaDay
  135. //
  136. // Adjust the day part of the current date
  137. //
  138. ////////////////////////////////////////////////////////////////////////////
  139. void AdjustDeltaDay(
  140. HWND hwnd,
  141. int iDay)
  142. {
  143. GetTime();
  144. if (wDateTime[DAY] != iDay)
  145. {
  146. wPrevDateTime[DAY] = wDateTime[DAY] = (WORD)iDay;
  147. fDateDirty = TRUE;
  148. //
  149. // Let our parent know that we changed.
  150. //
  151. FORWARD_WM_COMMAND( GetParent(hwnd),
  152. GetWindowLong(hwnd, GWL_ID),
  153. hwnd,
  154. CBN_SELCHANGE,
  155. SendMessage );
  156. }
  157. }
  158. int GetCalendarName(LPTSTR pszName, int cch)
  159. {
  160. TCHAR szDateString[100];
  161. SYSTEMTIME SystemTime;
  162. int cchResult = 0;
  163. SystemTime.wHour = wDateTime[HOUR];
  164. SystemTime.wMinute = wDateTime[MINUTE];
  165. SystemTime.wSecond = wDateTime[SECOND];
  166. SystemTime.wMilliseconds = 0;
  167. SystemTime.wMonth = wDateTime[MONTH];
  168. SystemTime.wDay = wDateTime[DAY];
  169. SystemTime.wYear = wDateTime[YEAR];
  170. if (0 != GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE,
  171. &SystemTime, NULL, szDateString, ARRAYSIZE(szDateString)))
  172. {
  173. if ( NULL != pszName )
  174. {
  175. StringCchCopy( pszName, cch, szDateString );
  176. }
  177. cchResult = lstrlen(szDateString);
  178. }
  179. return cchResult;
  180. }
  181. ////////////////////////////////////////////////////////////////////////////
  182. //
  183. // ChangeCurrentDate
  184. //
  185. // If we pass in iNewCol < 0, we simply want to invalidate todays date.
  186. // This is used when we gain and lose focus.
  187. //
  188. ////////////////////////////////////////////////////////////////////////////
  189. void ChangeCurrentDate(
  190. PCALINFO pci,
  191. int iNewCol,
  192. int iNewRow)
  193. {
  194. int iFirstDay, iRow, iColumn;
  195. RECT rc, rcT;
  196. GetClientRect(pci->hwnd, &rc);
  197. iFirstDay = GetFirstDayOfTheMonth();
  198. iColumn = (wDateTime[DAY] - 1 + iFirstDay) % 7;
  199. iRow = 1 + ((wDateTime[DAY] - 1 + iFirstDay) / 7);
  200. rcT.left = (((rc.right - rc.left) * iColumn) / 7) + cBorderX - cBorderSelect;
  201. rcT.right = rcT.left + (pci->cxChar * 2) + (2 * cBorderSelect);
  202. rcT.top = ((rc.bottom - rc.top) * iRow ) / 7 + cBorderY - cBorderSelect;
  203. rcT.bottom = rcT.top + pci->cyChar + (2 * cBorderSelect);
  204. InvalidateRect(pci->hwnd, &rcT, FALSE);
  205. if (iNewCol >= 0)
  206. {
  207. AdjustDeltaDay(pci->hwnd, ((iNewRow - 1) * 7) + iNewCol + 1 - iFirstDay);
  208. }
  209. }
  210. ////////////////////////////////////////////////////////////////////////////
  211. //
  212. // CalendarPaint
  213. //
  214. ////////////////////////////////////////////////////////////////////////////
  215. BOOL CalendarPaint(
  216. PCALINFO pci,
  217. HWND hwnd)
  218. {
  219. RECT rc, rcT;
  220. PAINTSTRUCT ps;
  221. HDC hdc;
  222. int iWeek, iWeekDay, iDay, iMaxDays;
  223. int iFirstDayOfWeek, iFirstDayOfMonth;
  224. TCHAR pszDate[3];
  225. TCHAR szShortDay[25];
  226. DWORD dwbkColor;
  227. COLORREF o_TextColor;
  228. LCID Locale;
  229. LANGID LangID = GetUserDefaultLangID();
  230. BOOL IsFELang = IS_FE_LANGUAGE(PRIMARYLANGID(LangID));
  231. iFirstDayOfMonth = GetFirstDayOfTheMonth();
  232. iMaxDays = GetDaysOfTheMonth(wDateTime[MONTH]);
  233. iDay = 1;
  234. pszDate[0] = TEXT(' ');
  235. pszDate[1] = TEXT('0');
  236. //
  237. // Paint the background of the dates page.
  238. //
  239. hdc = BeginPaint(hwnd, &ps);
  240. GetClientRect(hwnd, &rc);
  241. FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW));
  242. //
  243. // The day specifier.
  244. //
  245. rcT.left = rc.left;
  246. rcT.right = rc.right;
  247. rcT.top = rc.top;
  248. rcT.bottom = rc.top + ((rc.bottom - rc.top) / 7);
  249. FillRect(hdc, &rcT, GetSysColorBrush(COLOR_INACTIVECAPTION));
  250. //
  251. // Fill the page.
  252. //
  253. SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  254. SelectFont(hdc, pci->hfontCal);
  255. SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  256. //
  257. // See if we need to calculate the size of characters.
  258. //
  259. if (pci->cxChar == 0)
  260. {
  261. DrawText(hdc, TEXT("0"), 1, &rcT, DT_CALCRECT);
  262. pci->cxChar = rcT.right - rcT.left;
  263. pci->cyChar = rcT.bottom - rcT.top;
  264. DrawText(hdc, TEXT(" "), 1, &rcT, DT_CALCRECT);
  265. pci->cxBlank = rcT.right - rcT.left;
  266. }
  267. for (iWeek = 1; (iWeek < 7); iWeek++)
  268. {
  269. for (iWeekDay = iFirstDayOfMonth;
  270. (iWeekDay < 7) && (iDay <= iMaxDays);
  271. iWeekDay++)
  272. {
  273. rcT.left = ((((rc.right - rc.left) * iWeekDay) / 7)) + cBorderX;
  274. rcT.top = (((rc.bottom - rc.top) * iWeek) / 7) + cBorderY;
  275. rcT.right = rcT.left + 20;
  276. rcT.bottom = rcT.top + 20;
  277. if (pszDate[1] == TEXT('9'))
  278. {
  279. pszDate[1] = TEXT('0');
  280. if (pszDate[0] == TEXT(' '))
  281. {
  282. pszDate[0] = TEXT('1');
  283. }
  284. else
  285. {
  286. pszDate[0] = pszDate[0] + 1;
  287. }
  288. }
  289. else
  290. {
  291. pszDate[1] = pszDate[1] + 1;
  292. }
  293. if (wDateTime[DAY] == iDay)
  294. {
  295. dwbkColor = GetBkColor(hdc);
  296. SetBkColor(hdc, GetSysColor(COLOR_ACTIVECAPTION));
  297. o_TextColor = GetTextColor(hdc);
  298. SetTextColor(hdc, GetSysColor(COLOR_CAPTIONTEXT));
  299. }
  300. ExtTextOut( hdc,
  301. rcT.left,
  302. rcT.top,
  303. 0,
  304. &rcT,
  305. (LPTSTR)pszDate,
  306. 2,
  307. NULL );
  308. //
  309. // If we drew it inverted - put it back.
  310. //
  311. if (wDateTime[DAY] == iDay)
  312. {
  313. //
  314. // If we have the focus we also need to draw the focus
  315. // rectangle for this item.
  316. //
  317. if (pci->fFocus)
  318. {
  319. rcT.bottom = rcT.top + pci->cyChar;
  320. if (iDay <= 9)
  321. {
  322. rcT.right = rcT.left + pci->cxChar + pci->cxBlank;
  323. }
  324. else
  325. {
  326. rcT.right = rcT.left + 2 * pci->cxChar;
  327. }
  328. DrawFocusRect(hdc, &rcT);
  329. }
  330. SetBkColor(hdc, dwbkColor);
  331. SetTextColor(hdc, o_TextColor);
  332. }
  333. iFirstDayOfMonth = 0;
  334. iDay++;
  335. }
  336. }
  337. //
  338. // Set the FONT color for the SMTWTFS line.
  339. //
  340. dwbkColor = SetBkColor(hdc, GetSysColor(COLOR_INACTIVECAPTION));
  341. SetTextColor(hdc, GetSysColor(COLOR_INACTIVECAPTIONTEXT));
  342. iFirstDayOfWeek = GetFirstDayOfAnyWeek();
  343. if (!IsFELang)
  344. {
  345. //
  346. // Not a FE locale.
  347. //
  348. // If it's Arabic or Syriac, then we want to use the US locale to get the
  349. // first letter of the abbreviated day name to display in the calendar.
  350. //
  351. Locale = ((PRIMARYLANGID(LangID) == LANG_ARABIC) || (PRIMARYLANGID(LangID) == LANG_SYRIAC))
  352. ? MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT)
  353. : LOCALE_USER_DEFAULT;
  354. for (iWeekDay = 0; (iWeekDay < 7); iWeekDay++)
  355. {
  356. GetLocaleInfo( Locale,
  357. LOCALE_SABBREVDAYNAME1 + (iWeekDay + iFirstDayOfWeek) % 7,
  358. szShortDay,
  359. sizeof(szShortDay) / sizeof(TCHAR) );
  360. if (*szShortDay)
  361. {
  362. *szShortDay = (TCHAR)CharUpper((LPTSTR)(DWORD_PTR)*szShortDay);
  363. }
  364. TextOut( hdc,
  365. (((rc.right - rc.left) * iWeekDay) / 7) + cBorderX,
  366. cBorderY,
  367. szShortDay,
  368. 1 );
  369. }
  370. }
  371. else
  372. {
  373. //
  374. // FE Locale.
  375. //
  376. for (iWeekDay = 0; (iWeekDay < 7); iWeekDay++)
  377. {
  378. GetLocaleInfo( LOCALE_USER_DEFAULT,
  379. LOCALE_SABBREVDAYNAME1 + (iWeekDay + iFirstDayOfWeek) % 7,
  380. szShortDay,
  381. sizeof(szShortDay) / sizeof(TCHAR) );
  382. if (*szShortDay)
  383. {
  384. *szShortDay = (TCHAR)CharUpper((LPTSTR)(DWORD_PTR)*szShortDay);
  385. }
  386. if ((PRIMARYLANGID(LangID) == LANG_CHINESE) &&
  387. (lstrlen(szShortDay) == 3 ))
  388. {
  389. TextOut( hdc,
  390. (((rc.right - rc.left) * iWeekDay) / 7) + cBorderX,
  391. cBorderY,
  392. (LangID == MAKELANGID( LANG_CHINESE,
  393. SUBLANG_CHINESE_HONGKONG ))
  394. ? szShortDay
  395. : szShortDay + 2,
  396. 1 );
  397. }
  398. else
  399. {
  400. TextOut( hdc,
  401. (((rc.right - rc.left) * iWeekDay) / 7) + cBorderX,
  402. cBorderY,
  403. szShortDay,
  404. lstrlen(szShortDay) );
  405. }
  406. }
  407. }
  408. SetBkColor(hdc, dwbkColor);
  409. EndPaint(hwnd, &ps);
  410. return (TRUE);
  411. }
  412. ////////////////////////////////////////////////////////////////////////////
  413. //
  414. // IsValidClick
  415. //
  416. ////////////////////////////////////////////////////////////////////////////
  417. BOOL IsValidClick(
  418. HWND hwnd,
  419. int x,
  420. int y)
  421. {
  422. int iT;
  423. if (y == 0)
  424. {
  425. return (FALSE);
  426. }
  427. iT = GetFirstDayOfTheMonth();
  428. if ((y == 1) && (x < iT))
  429. {
  430. return (FALSE);
  431. }
  432. iT += GetDaysOfTheMonth(wDateTime[MONTH]) - 1;
  433. if (y > ((iT / 7) + 1))
  434. {
  435. return (FALSE);
  436. }
  437. if ((y == ((iT / 7) + 1)) && (x > (iT % 7)))
  438. {
  439. return (FALSE);
  440. }
  441. return (TRUE);
  442. }
  443. ////////////////////////////////////////////////////////////////////////////
  444. //
  445. // HandleDateChange
  446. //
  447. ////////////////////////////////////////////////////////////////////////////
  448. BOOL HandleDateChange(
  449. PCALINFO pci,
  450. int x,
  451. int y)
  452. {
  453. RECT rc, rcT;
  454. int ix, iy;
  455. GetClientRect(pci->hwnd, &rc);
  456. ix = (x * 7) / (rc.right - rc.left);
  457. iy = (y * 7) / (rc.bottom - rc.top);
  458. if (IsValidClick(pci->hwnd, ix, iy))
  459. {
  460. rcT.left = (((rc.right - rc.left) * ix)/ 7) + cBorderX - cBorderSelect;
  461. rcT.right = rcT.left + (2 * pci->cxChar) + (2 * cBorderSelect);
  462. rcT.top = ((rc.bottom - rc.top) * iy) / 7 + cBorderY - cBorderSelect;
  463. rcT.bottom = rcT.top + pci->cyChar + (2 * cBorderSelect);
  464. InvalidateRect(pci->hwnd, &rcT, FALSE);
  465. ChangeCurrentDate( pci,
  466. (x * 7) / (rc.right - rc.left),
  467. (y * 7) / (rc.bottom - rc.top) );
  468. NotifyWinEvent(EVENT_OBJECT_NAMECHANGE , pci->hwnd, OBJID_WINDOW, CHILDID_SELF);
  469. return (TRUE);
  470. }
  471. else
  472. {
  473. return (FALSE);
  474. }
  475. }
  476. ////////////////////////////////////////////////////////////////////////////
  477. //
  478. // HandleKeyDown
  479. //
  480. ////////////////////////////////////////////////////////////////////////////
  481. void HandleKeyDown(
  482. PCALINFO pci,
  483. int vk,
  484. LPARAM lParam)
  485. {
  486. RECT rcT;
  487. //
  488. // First thing, lets try to figure out what the current x and y is.
  489. //
  490. int ix = GetLocalWeekday();
  491. int iy = (wDateTime[DAY] + GetFirstDayOfTheMonth() - 1) / 7;
  492. switch (vk)
  493. {
  494. case ( VK_LEFT ) :
  495. {
  496. ix--;
  497. if (ix < 0)
  498. {
  499. ix = 6;
  500. iy--;
  501. }
  502. break;
  503. }
  504. case ( VK_RIGHT ) :
  505. {
  506. ix++;
  507. if (ix == 7)
  508. {
  509. ix = 0;
  510. iy++;
  511. }
  512. break;
  513. }
  514. case ( VK_UP ) :
  515. {
  516. iy--;
  517. break;
  518. }
  519. case ( VK_DOWN ) :
  520. {
  521. iy++;
  522. break;
  523. }
  524. default :
  525. {
  526. //
  527. // Ignore the character.
  528. //
  529. return;
  530. }
  531. }
  532. //
  533. // The y's are offset for the days of the week.
  534. //
  535. iy++;
  536. if (!IsValidClick(pci->hwnd, ix, iy))
  537. {
  538. return;
  539. }
  540. GetClientRect(pci->hwnd, &rcT);
  541. rcT.left = ((rcT.right * ix) / 7) + cBorderX - cBorderSelect;
  542. rcT.right = rcT.left + (2 * pci->cxChar) + (2 * cBorderSelect);
  543. rcT.top = (rcT.bottom * iy) / 7 + cBorderY - cBorderSelect;
  544. rcT.bottom = rcT.top + pci->cyChar + (2 * cBorderSelect);
  545. InvalidateRect(pci->hwnd, &rcT, FALSE);
  546. //
  547. // First try, simply call to change the date.
  548. //
  549. ChangeCurrentDate(pci, ix, iy);
  550. NotifyWinEvent(EVENT_OBJECT_NAMECHANGE , pci->hwnd, OBJID_WINDOW, CHILDID_SELF);
  551. }
  552. ////////////////////////////////////////////////////////////////////////////
  553. //
  554. // CalWndProc
  555. //
  556. ////////////////////////////////////////////////////////////////////////////
  557. LRESULT CALLBACK CalWndProc(
  558. HWND hwnd,
  559. UINT message,
  560. WPARAM wParam,
  561. LPARAM lParam)
  562. {
  563. PCALINFO pci;
  564. pci = (PCALINFO)GetWindowLongPtr(hwnd, 0);
  565. switch (message)
  566. {
  567. case ( WM_CREATE ) :
  568. {
  569. pci = (PCALINFO)LocalAlloc(LPTR, sizeof(CALINFO));
  570. if (pci == 0)
  571. {
  572. return (-1);
  573. }
  574. pci->hwnd = hwnd;
  575. SetWindowLongPtr(hwnd, 0, (LONG_PTR)pci);
  576. GetDate();
  577. break;
  578. }
  579. case ( WM_NCDESTROY ) :
  580. {
  581. if (pci)
  582. {
  583. LocalFree((HLOCAL)pci);
  584. }
  585. break;
  586. }
  587. case ( WM_SETFONT ) :
  588. {
  589. if (wParam)
  590. {
  591. pci->hfontCal = (HFONT)wParam;
  592. pci->cxChar = 0;
  593. }
  594. break;
  595. }
  596. case ( WM_GETTEXT ) :
  597. {
  598. return GetCalendarName((LPTSTR)lParam, (int)wParam);
  599. }
  600. case ( WM_GETTEXTLENGTH ) :
  601. {
  602. return GetCalendarName(NULL, 0);
  603. }
  604. case ( WM_PAINT ) :
  605. {
  606. CalendarPaint(pci, hwnd);
  607. break;
  608. }
  609. case ( WM_LBUTTONDOWN ) :
  610. {
  611. SetFocus(hwnd);
  612. HandleDateChange(pci, LOWORD(lParam), HIWORD(lParam));
  613. break;
  614. }
  615. case ( WM_SETFOCUS ) :
  616. {
  617. pci->fFocus = TRUE;
  618. ChangeCurrentDate(pci, -1, -1);
  619. break;
  620. }
  621. case ( WM_KILLFOCUS ) :
  622. {
  623. pci->fFocus = FALSE;
  624. ChangeCurrentDate(pci, -1, -1);
  625. break;
  626. }
  627. case ( WM_KEYDOWN ) :
  628. {
  629. HandleKeyDown(pci, (int)wParam, lParam);
  630. break;
  631. }
  632. case ( WM_GETDLGCODE ) :
  633. {
  634. return (DLGC_WANTARROWS);
  635. break;
  636. }
  637. default :
  638. {
  639. return ( DefWindowProc(hwnd, message, wParam, lParam) );
  640. }
  641. }
  642. return (0);
  643. }
  644. ////////////////////////////////////////////////////////////////////////////
  645. //
  646. // CalendarInit
  647. //
  648. ////////////////////////////////////////////////////////////////////////////
  649. TCHAR const c_szCalClass[] = CALENDAR_CLASS;
  650. BOOL CalendarInit(
  651. HANDLE hInstance)
  652. {
  653. WNDCLASS wc;
  654. if (!GetClassInfo(hInstance, c_szCalClass, &wc))
  655. {
  656. wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  657. wc.cbClsExtra = 0;
  658. wc.cbWndExtra = sizeof(PCALINFO);
  659. wc.hCursor = NULL;
  660. wc.hbrBackground = NULL;
  661. wc.hIcon = NULL;
  662. wc.lpszMenuName = NULL;
  663. wc.lpszClassName = c_szCalClass;
  664. wc.hInstance = hInstance;
  665. wc.lpfnWndProc = CalWndProc;
  666. return (RegisterClass(&wc));
  667. }
  668. return (TRUE);
  669. }