Source code of Windows XP (NT5)
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.

578 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. timectrl.c
  5. Abstract:
  6. For implementing a dialog control for setting time values
  7. Environment:
  8. Fax driver user interface
  9. Revision History:
  10. 01/16/96 -davidx-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include "faxlib.h"
  16. #include "timectrl.h"
  17. #include <commctrl.h>
  18. #include <windowsx.h>
  19. //
  20. // Static time format information
  21. //
  22. static BOOL timeCtrlInitialized = FALSE;
  23. static UINT use24Hour;
  24. static UINT hourLeadingZero;
  25. static TCHAR timeSep[8];
  26. static TCHAR amSuffix[8];
  27. static TCHAR pmSuffix[8];
  28. static TCHAR intlApplet[] = TEXT("Intl");
  29. static TCHAR use24HourKey[] = TEXT("iTime");
  30. static TCHAR hourLeadingZeroKey[] = TEXT("iTLZero");
  31. static TCHAR timeSepKey[] = TEXT("sTime");
  32. static TCHAR amSuffixKey[] = TEXT("s1159");
  33. static TCHAR pmSuffixKey[] = TEXT("s2359");
  34. static TCHAR timeSepDefault[] = TEXT(":");
  35. static TCHAR amSuffixDefault[] = TEXT("AM");
  36. static TCHAR pmSuffixDefault[] = TEXT("PM");
  37. VOID
  38. InitStaticValues(
  39. VOID
  40. )
  41. /*++
  42. Routine Description:
  43. One time initialization of the time control module
  44. Arguments:
  45. NONE
  46. Return Value:
  47. NONE
  48. --*/
  49. {
  50. if (! timeCtrlInitialized) {
  51. //
  52. // We only need to perform the initialization once.
  53. // Make sure to modify the global data inside a critical section.
  54. //
  55. use24Hour = GetProfileInt(intlApplet, use24HourKey, FALSE);
  56. hourLeadingZero = GetProfileInt(intlApplet, hourLeadingZeroKey, TRUE);
  57. GetProfileString(intlApplet,
  58. timeSepKey,
  59. timeSepDefault,
  60. timeSep,
  61. sizeof(timeSep) / sizeof(TCHAR));
  62. GetProfileString(intlApplet,
  63. amSuffixKey,
  64. amSuffixDefault,
  65. amSuffix,
  66. sizeof(amSuffix) / sizeof(TCHAR));
  67. GetProfileString(intlApplet,
  68. pmSuffixKey,
  69. pmSuffixDefault,
  70. pmSuffix,
  71. sizeof(pmSuffix) / sizeof(TCHAR));
  72. timeCtrlInitialized = TRUE;
  73. Verbose(("Use 24-hour format: %d\n", use24Hour));
  74. Verbose(("Hour leading zero: %d\n", hourLeadingZero));
  75. Verbose(("Time separator: %ws\n", timeSep));
  76. Verbose(("AM suffix: %ws\n", amSuffix));
  77. Verbose(("PM suffix: %ws\n", pmSuffix));
  78. }
  79. }
  80. VOID
  81. EnableTimeControl(
  82. HWND hDlg,
  83. INT id,
  84. BOOL enabled
  85. )
  86. /*++
  87. Routine Description:
  88. Enable or disable a time control
  89. Arguments:
  90. hDlg - Specifies the dialog window containing the time control
  91. id - Identifies the time control
  92. enabled - Whether to enable or disable the time control
  93. Return Value:
  94. NONE
  95. --*/
  96. {
  97. // EnableWindow(GetDlgItem(hDlg, IDC_SENDTIME), enabled);
  98. EnableWindow(GetDlgItem(hDlg, id+TC_HOUR), enabled);
  99. InvalidateRect(GetDlgItem(hDlg, id+TC_TIME_SEP), NULL, FALSE);
  100. EnableWindow(GetDlgItem(hDlg, id+TC_MINUTE), enabled);
  101. EnableWindow(GetDlgItem(hDlg, id+TC_AMPM), enabled);
  102. EnableWindow(GetDlgItem(hDlg, id+TC_ARROW), enabled);
  103. }
  104. VOID
  105. SetHourMinuteValue(
  106. HWND hDlg,
  107. INT id,
  108. INT part,
  109. INT value
  110. )
  111. /*++
  112. Routine Description:
  113. Set the hour or minute value
  114. Arguments:
  115. hDlg - Specifies the dialog window containing the time control
  116. id - Identifies the time control
  117. part - Whether we're setting hour or minute value
  118. value - Specifies the new hour or minute value
  119. Return Value:
  120. NONE
  121. --*/
  122. {
  123. TCHAR buffer[4];
  124. if (value < 0 || value > ((part == TC_MINUTE) ? 59 : 23))
  125. value = 0;
  126. if (part == TC_HOUR && !use24Hour) {
  127. SendDlgItemMessage(hDlg, id+TC_AMPM, LB_SETTOPINDEX, value / 12, 0);
  128. if ((value %= 12) == 0)
  129. value = 12;
  130. }
  131. wsprintf(buffer,
  132. (part == TC_MINUTE || hourLeadingZero) ? TEXT("%02d") : TEXT("%d"),
  133. value);
  134. SetDlgItemText(hDlg, id+part, buffer);
  135. }
  136. VOID
  137. InitTimeControl(
  138. HWND hDlg,
  139. INT id,
  140. PFAX_TIME pTimeVal
  141. )
  142. /*++
  143. Routine Description:
  144. Setting the current value of a time control
  145. Arguments:
  146. hDlg - Specifies the dialog window containing the time control
  147. id - Identifies the time control
  148. pTimeVal - Specifies the new value for the time control
  149. Return Value:
  150. NONE
  151. --*/
  152. {
  153. HWND hwnd, hwndArrow;
  154. //
  155. // Make sure the static global information is initialized
  156. //
  157. InitStaticValues();
  158. //
  159. // Display the time separator
  160. //
  161. SetDlgItemText(hDlg, id+TC_TIME_SEP, timeSep);
  162. //
  163. // Display the AM/PM suffix if necessary
  164. //
  165. if (hwnd = GetDlgItem(hDlg, id+TC_AMPM)) {
  166. if (! use24Hour) {
  167. SendMessage(hwnd, LB_INSERTSTRING, 0, (LPARAM) &amSuffix[0]);
  168. SendMessage(hwnd, LB_INSERTSTRING, 1, (LPARAM) &pmSuffix[0]);
  169. } else
  170. EnableWindow(hwnd, FALSE);
  171. }
  172. //
  173. // Display hour and minute values
  174. //
  175. SetHourMinuteValue(hDlg, id, TC_HOUR, pTimeVal->Hour);
  176. SetHourMinuteValue(hDlg, id, TC_MINUTE, pTimeVal->Minute);
  177. //
  178. // Connect the updown arrow to the minute field by default
  179. //
  180. if ((hwnd = GetDlgItem(hDlg, id+TC_MINUTE)) && (hwndArrow = GetDlgItem(hDlg, id+TC_ARROW))) {
  181. UDACCEL udAccel[2];
  182. udAccel[0].nSec = 0;
  183. udAccel[0].nInc = 1;
  184. udAccel[1].nSec = 2;
  185. udAccel[1].nInc = 5;
  186. SendMessage(hwndArrow, UDM_SETRANGE, 0, MAKELPARAM(59, 0));
  187. SendMessage(hwndArrow, UDM_SETACCEL, 2, (LPARAM) &udAccel[0]);
  188. SendMessage(hwndArrow, UDM_SETBUDDY, (WPARAM) hwnd, 0);
  189. }
  190. }
  191. BOOL
  192. GetHourMinuteValue(
  193. HWND hDlg,
  194. INT id,
  195. INT part,
  196. PWORD pValue
  197. )
  198. /*++
  199. Routine Description:
  200. Retrieve the current hour or minute value
  201. Arguments:
  202. hDlg - Specifies the dialog window containing the time control
  203. id - Identifies the time control
  204. part - Whether we're interest in hour or minute value
  205. pValue - Buffer for storing the current hour value
  206. Return Value:
  207. TRUE if successful, FALSE otherwise
  208. --*/
  209. {
  210. INT value, minVal, maxVal;
  211. BOOL success;
  212. //
  213. // Read the text field as an integer value
  214. //
  215. value = GetDlgItemInt(hDlg, id+part, &success, FALSE);
  216. //
  217. // Make sure the input value is valid
  218. //
  219. if (! success)
  220. value = 0;
  221. else {
  222. if (part == TC_MINUTE)
  223. minVal = 0, maxVal = 59;
  224. else if (use24Hour)
  225. minVal = 0, maxVal = 23;
  226. else
  227. minVal = 1, maxVal = 12;
  228. success = FALSE;
  229. if (value < minVal)
  230. value = minVal;
  231. else if (value > maxVal)
  232. value = maxVal;
  233. else
  234. success = TRUE;
  235. }
  236. //
  237. // Convert AM/PM hours to absolute number between 0-23
  238. //
  239. if (part == TC_HOUR && !use24Hour) {
  240. if (SendDlgItemMessage(hDlg, id+TC_AMPM, LB_GETTOPINDEX, 0, 0)) {
  241. // PM
  242. if (value != 12)
  243. value += 12;
  244. } else {
  245. // AM
  246. if (value == 12)
  247. value = 0;
  248. }
  249. }
  250. *pValue = (WORD) value;
  251. return success;
  252. }
  253. VOID
  254. GetTimeControlValue(
  255. HWND hDlg,
  256. INT id,
  257. PFAX_TIME pTimeVal
  258. )
  259. /*++
  260. Routine Description:
  261. Retrieve the current value of a time control
  262. Arguments:
  263. hDlg - Specifies the dialog window containing the time control
  264. id - Identifies the time control
  265. pTimeVal - Buffer for storing the current time value
  266. Return Value:
  267. NONE
  268. --*/
  269. {
  270. GetHourMinuteValue(hDlg, id, TC_HOUR, &pTimeVal->Hour);
  271. GetHourMinuteValue(hDlg, id, TC_MINUTE, &pTimeVal->Minute);
  272. }
  273. BOOL
  274. HandleTimeControl(
  275. HWND hDlg,
  276. UINT message,
  277. WPARAM wParam,
  278. LPARAM lParam,
  279. INT id,
  280. INT part
  281. )
  282. /*++
  283. Routine Description:
  284. Handle dialog messages intended for a time control
  285. Arguments:
  286. hDlg - Specifies the dialog window containing the time control
  287. message, wParam, lParam - Parameters passed to the dialog procedure
  288. id - Identifies the time control
  289. part - Identifies what part of the time control in question
  290. Return Value:
  291. TRUE if the message is handled, FALSE otherwise
  292. --*/
  293. {
  294. HWND hwnd, hwndArrow;
  295. UDACCEL udAccel[2];
  296. WORD wMax, wMin;
  297. switch (message) {
  298. case WM_COMMAND:
  299. //
  300. // Make sure the control is indeed ours
  301. //
  302. hwnd = GetDlgItem(hDlg, id+part);
  303. hwndArrow = GetDlgItem(hDlg, id+TC_ARROW);
  304. if (hwnd != GET_WM_COMMAND_HWND(wParam, lParam)) {
  305. Warning(("Bad window handle\n"));
  306. return FALSE;
  307. }
  308. switch (GET_WM_COMMAND_CMD(wParam, lParam)) {
  309. case LBN_SETFOCUS:
  310. //
  311. // AM/PM list box is coming into focus
  312. //
  313. Assert(part == TC_AMPM);
  314. udAccel[0].nSec = 0;
  315. udAccel[0].nInc = 1;
  316. SendMessage(hwnd, LB_SETCURSEL, SendMessage(hwnd, LB_GETTOPINDEX, 0, 0), 0);
  317. SendMessage(hwndArrow, UDM_SETRANGE, 0, MAKELPARAM(1, 0));
  318. SendMessage(hwndArrow, UDM_SETACCEL, 1, (LPARAM) &udAccel[0]);
  319. SendMessage(hwndArrow, UDM_SETBUDDY, (WPARAM) hwnd, 0);
  320. break;
  321. case LBN_KILLFOCUS:
  322. //
  323. // Leaving AM/PM listbox
  324. //
  325. Assert(part == TC_AMPM);
  326. SendMessage(hwnd, LB_SETCURSEL, (WPARAM) -1, 0);
  327. SendMessage(hwndArrow, UDM_SETBUDDY, 0, 0);
  328. break;
  329. case EN_SETFOCUS:
  330. //
  331. // Entering hour or minute text field
  332. //
  333. Assert(part == TC_HOUR || part == TC_MINUTE);
  334. udAccel[0].nSec = 0;
  335. udAccel[0].nInc = 1;
  336. udAccel[1].nSec = 2;
  337. if (part == TC_MINUTE) {
  338. wMin = 0, wMax = 59;
  339. udAccel[1].nInc = 5;
  340. } else {
  341. udAccel[1].nInc = 1;
  342. if (use24Hour)
  343. wMin = 0, wMax = 23;
  344. else
  345. wMin = 1, wMax = 12;
  346. }
  347. SendMessage(hwndArrow, UDM_SETRANGE, 0, MAKELPARAM(wMax, wMin));
  348. SendMessage(hwndArrow, UDM_SETACCEL, 2, (LPARAM) &udAccel[0]);
  349. SendMessage(hwndArrow, UDM_SETBUDDY, (WPARAM) hwnd, 0);
  350. SendMessage(hwnd, EM_SETSEL, 0, -1);
  351. break;
  352. case EN_CHANGE:
  353. //
  354. // Changing hour or minute field
  355. //
  356. Assert(part == TC_HOUR || part == TC_MINUTE);
  357. if (!GetHourMinuteValue(hDlg, id, part, &wMax) && GetWindowTextLength(hwnd)) {
  358. MessageBeep(MB_ICONASTERISK);
  359. SendMessage(hwnd, EM_UNDO, 0, 0);
  360. }
  361. break;
  362. case EN_KILLFOCUS:
  363. //
  364. // Leaving hour or minute text field
  365. //
  366. Assert(part == TC_HOUR || part == TC_MINUTE);
  367. GetHourMinuteValue(hDlg, id, part, &wMax);
  368. SetHourMinuteValue(hDlg, id, part, wMax);
  369. SendMessage(hwndArrow, UDM_SETBUDDY, 0, 0);
  370. break;
  371. }
  372. return TRUE;
  373. case WM_CTLCOLORLISTBOX:
  374. case WM_CTLCOLORSTATIC:
  375. case WM_CTLCOLOREDIT:
  376. case WM_CTLCOLOR:
  377. //
  378. // Set the background color of the time control to the color of editable text
  379. // or static text depending on whether the control is disabled or enabled
  380. //
  381. hwnd = GET_WM_CTLCOLOR_HWND(wParam, lParam, message);
  382. if (hwnd == GetDlgItem(hDlg, id + TC_HOUR) ||
  383. hwnd == GetDlgItem(hDlg, id + TC_MINUTE) ||
  384. hwnd == GetDlgItem(hDlg, id + TC_TIME_SEP) ||
  385. hwnd == GetDlgItem(hDlg, id + TC_AMPM))
  386. {
  387. message = part ? WM_CTLCOLOREDIT : WM_CTLCOLORSTATIC;
  388. return (BOOL)DefWindowProc(hDlg, message, wParam, lParam);
  389. }
  390. break;
  391. }
  392. return FALSE;
  393. }