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.

659 lines
18 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. display.c
  5. Abstract: Tablet PC Display Property Sheet module.
  6. Environment:
  7. User mode
  8. Author:
  9. Michael Tsang (MikeTs) 14-Jun-2000
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. #define BRIGHTSCALE_MIN 0
  14. #define BRIGHTSCALE_MAX 15
  15. #define BRIGHTSCALE_LO 1
  16. #define BRIGHTSCALE_HI 15
  17. HANDLE ghBackLight = INVALID_HANDLE_VALUE;
  18. HMODULE ghmodSMAPI = NULL;
  19. FARPROC gpfnCallSMAPI = NULL;
  20. ERRMAP SMAPIErrMap[] =
  21. {
  22. RT_ERR_INSTRETCHMODE, IDSERR_SMAPI_INSTRETCHMODE,
  23. RT_ERR_INDUALAPPMODE, IDSERR_SMAPI_INDUALAPPMODE,
  24. RT_ERR_INDUALVIEWMODE, IDSERR_SMAPI_INDUALVIEWMODE,
  25. RT_ERR_INRGBPROJMODE, IDSERR_SMAPI_INRGBPROJMODE,
  26. RT_ERR_INVIRTUALSCREEN, IDSERR_SMAPI_INVIRTUALSCREEN,
  27. RT_ERR_INVIRTUALREFRESH, IDSERR_SMAPI_INVIRTUALREFRESH,
  28. RT_ERR_INROTATEMODE, IDSERR_SMAPI_INROTATEMODE,
  29. RT_ERR_2NDMONITORON, IDSERR_SMAPI_2NDMONITORON,
  30. RT_ERR_WRONGHW, IDSERR_SMAPI_WRONGHW,
  31. RT_ERR_CLRDEPTH, IDSERR_SMAPI_CLRDEPTH,
  32. RT_ERR_MEMORY, IDSERR_SMAPI_MEMORY,
  33. RT_ERR_SETMODE, IDSERR_SMAPI_SETMODE,
  34. RT_ERR_DIRECTION, IDSERR_SMAPI_DIRECTION,
  35. RT_ERR_CAPTUREON, IDSERR_SMAPI_CAPTUREON,
  36. RT_ERR_VIDEOON, IDSERR_SMAPI_VIDEOON,
  37. RT_ERR_DDRAWON, IDSERR_SMAPI_DDRAWON,
  38. RT_ERR_ALREADYSET, IDSERR_SMAPI_ALREADYSET,
  39. 0, 0
  40. };
  41. SMBLITE_BRIGHTNESS gBrightness = {0};
  42. BOOL gfPortraitMode = FALSE;
  43. DWORD gDisplayHelpIDs[] =
  44. {
  45. IDC_ROTATE_GROUPBOX, IDH_ROTATE,
  46. 0, 0
  47. };
  48. /*++
  49. @doc EXTERNAL
  50. @func INT_PTR | DisplayDlgProc |
  51. Dialog procedure for the display page.
  52. @parm IN HWND | hwnd | Window handle.
  53. @parm IN UINT | uMsg | Message.
  54. @parm IN WPARAM | wParam | Word Parameter.
  55. @parm IN LPARAM | lParam | Long Parameter.
  56. @rvalue Return value depends on the message.
  57. --*/
  58. INT_PTR APIENTRY
  59. DisplayDlgProc(
  60. IN HWND hwnd,
  61. IN UINT uMsg,
  62. IN WPARAM wParam,
  63. IN LPARAM lParam
  64. )
  65. {
  66. TRACEPROC("DisplayDlgProc", 2)
  67. INT_PTR rc = FALSE;
  68. static BOOL fPortrait = FALSE;
  69. static SMBLITE_BRIGHTNESS Brightness = {0};
  70. TRACEENTER(("(hwnd=%p,Msg=%s,wParam=%x,lParam=%x)\n",
  71. hwnd, LookupName(uMsg, WMMsgNames) , wParam, lParam));
  72. switch (uMsg)
  73. {
  74. case WM_INITDIALOG:
  75. rc = InitDisplayPage(hwnd);
  76. if (rc)
  77. {
  78. fPortrait = gfPortraitMode;
  79. Brightness = gBrightness;
  80. }
  81. else
  82. {
  83. EnableWindow(hwnd, FALSE);
  84. }
  85. break;
  86. case WM_DESTROY:
  87. if (ghmodSMAPI != NULL)
  88. {
  89. FreeLibrary(ghmodSMAPI);
  90. ghmodSMAPI = NULL;
  91. gpfnCallSMAPI = NULL;
  92. }
  93. if (ghBackLight != INVALID_HANDLE_VALUE)
  94. {
  95. if ((Brightness.bACValue != gBrightness.bACValue) ||
  96. (Brightness.bDCValue != gBrightness.bDCValue))
  97. {
  98. //
  99. // User must have canceled the setting, so restore
  100. // brightness to the original values.
  101. //
  102. SetBrightness(&gBrightness, FALSE);
  103. }
  104. CloseHandle(ghBackLight);
  105. ghBackLight = INVALID_HANDLE_VALUE;
  106. }
  107. break;
  108. case WM_DISPLAYCHANGE:
  109. gfPortraitMode = (LOWORD(lParam) < HIWORD(lParam));
  110. CheckRadioButton(hwnd,
  111. IDC_ROTATE_LANDSCAPE,
  112. IDC_ROTATE_PORTRAIT,
  113. gfPortraitMode? IDC_ROTATE_PORTRAIT:
  114. IDC_ROTATE_LANDSCAPE);
  115. break;
  116. case WM_NOTIFY:
  117. {
  118. NMHDR FAR *lpnm = (NMHDR FAR *)lParam;
  119. switch (lpnm->code)
  120. {
  121. case PSN_APPLY:
  122. {
  123. if (fPortrait ^ gfPortraitMode)
  124. {
  125. DWORD smrc;
  126. smrc = RotateScreen(fPortrait? RT_CLOCKWISE: 0);
  127. if (smrc == SMAPI_OK)
  128. {
  129. gfPortraitMode = fPortrait;
  130. }
  131. else
  132. {
  133. DWORD dwErr = MapError(smrc, SMAPIErrMap, FALSE);
  134. CheckRadioButton(hwnd,
  135. IDC_ROTATE_LANDSCAPE,
  136. IDC_ROTATE_PORTRAIT,
  137. gfPortraitMode?
  138. IDC_ROTATE_PORTRAIT:
  139. IDC_ROTATE_LANDSCAPE);
  140. if (dwErr == 0)
  141. {
  142. ErrorMsg(IDSERR_SMAPI_CALLFAILED, smrc);
  143. }
  144. else
  145. {
  146. ErrorMsg(dwErr);
  147. }
  148. }
  149. }
  150. if ((Brightness.bACValue != gBrightness.bACValue) ||
  151. (Brightness.bDCValue != gBrightness.bDCValue))
  152. {
  153. //
  154. // User has committed to the new values, save them.
  155. //
  156. if (SetBrightness(&Brightness, TRUE))
  157. {
  158. gBrightness = Brightness;
  159. }
  160. }
  161. break;
  162. }
  163. }
  164. break;
  165. }
  166. case WM_COMMAND:
  167. {
  168. switch (LOWORD(wParam))
  169. {
  170. case IDC_ROTATE_LANDSCAPE:
  171. fPortrait = FALSE;
  172. goto CheckRotation;
  173. case IDC_ROTATE_PORTRAIT:
  174. fPortrait = TRUE;
  175. CheckRotation:
  176. if ((HIWORD(wParam) == BN_CLICKED) &&
  177. !IsDlgButtonChecked(hwnd, LOWORD(wParam)))
  178. {
  179. //
  180. // Rotation has changed, mark the property
  181. // sheet dirty.
  182. //
  183. CheckRadioButton(hwnd,
  184. IDC_ROTATE_LANDSCAPE,
  185. IDC_ROTATE_PORTRAIT,
  186. LOWORD(wParam));
  187. SendMessage(GetParent(hwnd),
  188. PSM_CHANGED,
  189. (WPARAM)hwnd,
  190. 0);
  191. rc = TRUE;
  192. }
  193. break;
  194. }
  195. break;
  196. }
  197. #ifdef BACKLIGHT
  198. case WM_HSCROLL:
  199. {
  200. UCHAR BrightScale;
  201. BrightScale = (UCHAR)SendDlgItemMessage(hwnd,
  202. IDC_BRIGHTNESS_AC,
  203. TBM_GETPOS,
  204. 0,
  205. 0);
  206. Brightness.bACValue = BrightScale*(BRIGHTNESS_MAX + 1)/
  207. (BRIGHTSCALE_MAX + 1);
  208. BrightScale = (UCHAR)SendDlgItemMessage(hwnd,
  209. IDC_BRIGHTNESS_DC,
  210. TBM_GETPOS,
  211. 0,
  212. 0);
  213. Brightness.bDCValue = BrightScale*(BRIGHTNESS_MAX + 1)/
  214. (BRIGHTSCALE_MAX + 1);
  215. if ((Brightness.bACValue != gBrightness.bACValue) ||
  216. (Brightness.bDCValue != gBrightness.bDCValue))
  217. {
  218. if (SetBrightness(&Brightness, FALSE))
  219. {
  220. SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0);
  221. }
  222. }
  223. break;
  224. }
  225. #endif
  226. case WM_HELP:
  227. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  228. TEXT("tabletpc.hlp"),
  229. HELP_WM_HELP,
  230. (DWORD_PTR)gDisplayHelpIDs);
  231. break;
  232. case WM_CONTEXTMENU:
  233. WinHelp((HWND)wParam,
  234. TEXT("tabletpc.hlp"),
  235. HELP_CONTEXTMENU,
  236. (DWORD_PTR)gDisplayHelpIDs);
  237. break;
  238. }
  239. TRACEEXIT(("=%x\n", rc));
  240. return rc;
  241. } //DisplayDlgProc
  242. /*++
  243. @doc INTERNAL
  244. @func BOOL | InitDisplayPage |
  245. Initialize the display property page.
  246. @parm IN HWND | hwnd | Window handle.
  247. @rvalue SUCCESS | Returns TRUE.
  248. @rvalue FAILURE | Returns FALSE.
  249. --*/
  250. BOOL
  251. InitDisplayPage(
  252. IN HWND hwnd
  253. )
  254. {
  255. TRACEPROC("InitDisplayPage", 2)
  256. BOOL rc = FALSE;
  257. TRACEENTER(("(hwnd=%x)\n", hwnd));
  258. #ifdef BACKLIGHT
  259. SendDlgItemMessage(hwnd,
  260. IDC_BRIGHTNESS_AC,
  261. TBM_SETRANGE,
  262. TRUE,
  263. MAKELONG(BRIGHTSCALE_LO, BRIGHTSCALE_HI));
  264. SendDlgItemMessage(hwnd,
  265. IDC_BRIGHTNESS_DC,
  266. TBM_SETRANGE,
  267. TRUE,
  268. MAKELONG(BRIGHTSCALE_LO, BRIGHTSCALE_HI));
  269. #endif
  270. ghmodSMAPI = LoadLibrary(TEXT("smhook.dll"));
  271. if (ghmodSMAPI != NULL)
  272. {
  273. gpfnCallSMAPI = GetProcAddress(ghmodSMAPI, "CallSMAPI");
  274. if (gpfnCallSMAPI != NULL)
  275. {
  276. LONG cxScreen, cyScreen;
  277. cxScreen = GetSystemMetrics(SM_CXSCREEN);
  278. cyScreen = GetSystemMetrics(SM_CYSCREEN);
  279. gfPortraitMode = (cxScreen < cyScreen);
  280. CheckRadioButton(hwnd,
  281. IDC_ROTATE_LANDSCAPE,
  282. IDC_ROTATE_PORTRAIT,
  283. gfPortraitMode? IDC_ROTATE_PORTRAIT:
  284. IDC_ROTATE_LANDSCAPE);
  285. #ifdef BACKLIGHT
  286. ghBackLight = CreateFile(SMBLITE_IOCTL_DEVNAME,
  287. GENERIC_READ | GENERIC_WRITE,
  288. FILE_SHARE_READ | FILE_SHARE_WRITE,
  289. NULL,
  290. OPEN_EXISTING,
  291. FILE_ATTRIBUTE_NORMAL,
  292. NULL);
  293. if (ghBackLight == INVALID_HANDLE_VALUE)
  294. {
  295. ErrorMsg(IDSERR_SMBLITE_OPENDEV, GetLastError());
  296. }
  297. else if (GetBrightness(&gBrightness))
  298. {
  299. LPARAM lParam;
  300. lParam = gBrightness.bACValue*(BRIGHTSCALE_MAX + 1)/
  301. (BRIGHTNESS_MAX + 1);
  302. SendDlgItemMessage(hwnd,
  303. IDC_BRIGHTNESS_AC,
  304. TBM_SETPOS,
  305. TRUE,
  306. lParam);
  307. lParam = gBrightness.bDCValue*(BRIGHTSCALE_MAX + 1)/
  308. (BRIGHTNESS_MAX + 1);
  309. SendDlgItemMessage(hwnd,
  310. IDC_BRIGHTNESS_DC,
  311. TBM_SETPOS,
  312. TRUE,
  313. lParam);
  314. }
  315. #endif
  316. rc = TRUE;
  317. }
  318. else
  319. {
  320. FreeLibrary(ghmodSMAPI);
  321. ghmodSMAPI = NULL;
  322. ErrorMsg(IDSERR_GETPROCADDR_SMAPI);
  323. }
  324. }
  325. else
  326. {
  327. ErrorMsg(IDSERR_LOADLIBRARY_SMAPI);
  328. }
  329. TRACEEXIT(("=%x\n", rc));
  330. return rc;
  331. } //InitDisplayPage
  332. /*++
  333. @doc EXTERNAL
  334. @func DWORD | SetRotation | Set display rotation mode.
  335. @parm IN DWORD | dwRotation | Specified the rotation.
  336. @rvalue SUCCESS | Returns TRUE.
  337. @rvalue FAILURE | Returns FALSE.
  338. --*/
  339. BOOL
  340. __stdcall
  341. SetRotation(
  342. IN DWORD dwRotation
  343. )
  344. {
  345. TRACEPROC("SetRotation", 2)
  346. BOOL rc = FALSE;
  347. BOOL fNeedUnload = FALSE;
  348. TRACEENTER(("(Rotation=%x)\n", dwRotation));
  349. if (gpfnCallSMAPI == NULL)
  350. {
  351. ghmodSMAPI = LoadLibrary(TEXT("smhook.dll"));
  352. if (ghmodSMAPI != NULL)
  353. {
  354. gpfnCallSMAPI = GetProcAddress(ghmodSMAPI, "CallSMAPI");
  355. if (gpfnCallSMAPI != NULL)
  356. {
  357. fNeedUnload = TRUE;
  358. }
  359. else
  360. {
  361. FreeLibrary(ghmodSMAPI);
  362. ghmodSMAPI = NULL;
  363. ErrorMsg(IDSERR_GETPROCADDR_SMAPI);
  364. }
  365. }
  366. else
  367. {
  368. ErrorMsg(IDSERR_LOADLIBRARY_SMAPI);
  369. }
  370. }
  371. if (gpfnCallSMAPI != NULL)
  372. {
  373. DWORD smrc, dwErr;
  374. smrc = RotateScreen(dwRotation);
  375. if (smrc == SMAPI_OK)
  376. {
  377. rc = TRUE;
  378. }
  379. else
  380. {
  381. dwErr = MapError(smrc, SMAPIErrMap, FALSE);
  382. if (dwErr == 0)
  383. {
  384. ErrorMsg(IDSERR_SMAPI_CALLFAILED, smrc);
  385. }
  386. else
  387. {
  388. ErrorMsg(dwErr);
  389. }
  390. }
  391. }
  392. if (fNeedUnload)
  393. {
  394. gpfnCallSMAPI = NULL;
  395. FreeLibrary(ghmodSMAPI);
  396. ghmodSMAPI = NULL;
  397. }
  398. TRACEEXIT(("=%x\n", rc));
  399. return rc;
  400. } //SetRotation
  401. /*++
  402. @doc INTERNAL
  403. @func DWORD | RotateScreen |
  404. Rotate the screen to the given orientation.
  405. @parm IN DWORD | dwRotation | Specified the rotation.
  406. @rvalue SUCCESS | Returns SMAPI_OK.
  407. @rvalue FAILURE | Returns SMAPI error code.
  408. --*/
  409. DWORD
  410. RotateScreen(
  411. IN DWORD dwRotation
  412. )
  413. {
  414. TRACEPROC("RotateScreen", 2)
  415. DWORD rc;
  416. TRACEENTER(("(Rotation=%d)\n", dwRotation));
  417. if (gpfnCallSMAPI != NULL)
  418. {
  419. if (dwRotation == 0)
  420. {
  421. rc = gpfnCallSMAPI(ROTATE_EXIT, 0, 0, 0);
  422. }
  423. else
  424. {
  425. if (gpfnCallSMAPI(ROTATE_STATUS, 0, 0, 0))
  426. {
  427. gpfnCallSMAPI(ROTATE_EXIT, 0, 0, 0);
  428. }
  429. rc = gpfnCallSMAPI(ROTATE_INIT, dwRotation, 0, 0);
  430. if (rc == SMAPI_OK)
  431. {
  432. //
  433. // The SMI driver has this dynamic mode table feature that
  434. // it may not report portrait display modes unless we
  435. // enumerate them. Therefore, we do display mode enumeration
  436. // just to force the SMI driver to load a display mode tablet
  437. // that support portrait modes.
  438. //
  439. EnumDisplayModes();
  440. rc = gpfnCallSMAPI(ROTATE_EXECUTE, NULL, dwRotation, 0);
  441. }
  442. }
  443. }
  444. else
  445. {
  446. rc = SMAPI_ERR_NODRV;
  447. }
  448. TRACEEXIT(("=%x\n", rc));
  449. return rc;
  450. } //RotateScreen
  451. /*++
  452. @doc INTERNAL
  453. @func VOID | EnumDisplayModes | Enumerate display modes to force
  454. SMI driver to dynamically load a mode table that supports
  455. Portrait modes.
  456. @parm None.
  457. @rvalue None.
  458. --*/
  459. VOID
  460. EnumDisplayModes(
  461. VOID
  462. )
  463. {
  464. TRACEPROC("EnumDisplayModes", 3)
  465. DWORD i;
  466. DEVMODE DevMode;
  467. TRACEENTER(("()\n"));
  468. for (i = 0; EnumDisplaySettings(NULL, i, &DevMode); ++i)
  469. {
  470. //
  471. // Don't have to do anything.
  472. //
  473. }
  474. TRACEEXIT(("!\n"));
  475. return;
  476. } //EnumDisplayModes
  477. /*++
  478. @doc INTERNAL
  479. @func BOOL | GetBrightness | Call the backlight driver to get
  480. LCD brightness.
  481. @parm OUT PSMBLITE_BRIGHTNESS | Brightness | Brightness values.
  482. @rvalue SUCCESS | Returnes TRUE.
  483. @rvalue FAILURE | Returnes FALSE.
  484. --*/
  485. BOOL
  486. GetBrightness(
  487. OUT PSMBLITE_BRIGHTNESS Brightness
  488. )
  489. {
  490. TRACEPROC("GetBrightness", 3)
  491. BOOL rc = FALSE;
  492. TRACEENTER(("(Brightness=%p)\n", Brightness));
  493. if (ghBackLight != INVALID_HANDLE_VALUE)
  494. {
  495. DWORD dwcbReturned;
  496. rc = DeviceIoControl(ghBackLight,
  497. IOCTL_SMBLITE_GETBRIGHTNESS,
  498. NULL,
  499. 0,
  500. Brightness,
  501. sizeof(*Brightness),
  502. &dwcbReturned,
  503. NULL);
  504. if (rc == FALSE)
  505. {
  506. ErrorMsg(IDSERR_SMBLITE_DEVIOCTL, GetLastError());
  507. }
  508. }
  509. else
  510. {
  511. ErrorMsg(IDSERR_SMBLITE_NODEVICE);
  512. }
  513. TRACEEXIT(("=%x (AC=%d,DC=%d)\n",
  514. rc, Brightness->bACValue, Brightness->bDCValue));
  515. return rc;
  516. } //GetBrightness
  517. /*++
  518. @doc INTERNAL
  519. @func BOOL | SetBrightness | Call the backlight driver to set
  520. LCD brightness.
  521. @parm IN PSMBLITE_BRIGHTNESS | Brightness | Brightness values.'
  522. @parm IN BOOLEAN | fSaveSettings | If TRUE, save new brightness in the
  523. registry.
  524. @rvalue SUCCESS | Returnes TRUE.
  525. @rvalue FAILURE | Returnes FALSE.
  526. --*/
  527. BOOL
  528. SetBrightness(
  529. IN PSMBLITE_BRIGHTNESS Brightness,
  530. IN BOOLEAN fSaveSettings
  531. )
  532. {
  533. TRACEPROC("SetBrightness", 3)
  534. BOOL rc = FALSE;
  535. TRACEENTER(("(Brightness=%p,ACValue=%d,DCValue=%d)\n",
  536. Brightness, Brightness->bACValue, Brightness->bDCValue));
  537. if (ghBackLight != INVALID_HANDLE_VALUE)
  538. {
  539. SMBLITE_SETBRIGHTNESS SetLCD;
  540. DWORD dwcbReturned;
  541. SetLCD.Brightness = *Brightness;
  542. SetLCD.fSaveSettings = fSaveSettings;
  543. rc = DeviceIoControl(ghBackLight,
  544. IOCTL_SMBLITE_SETBRIGHTNESS,
  545. &SetLCD,
  546. sizeof(SetLCD),
  547. NULL,
  548. 0,
  549. &dwcbReturned,
  550. NULL);
  551. if (rc == FALSE)
  552. {
  553. ErrorMsg(IDSERR_SMBLITE_DEVIOCTL, GetLastError());
  554. }
  555. }
  556. else
  557. {
  558. ErrorMsg(IDSERR_SMBLITE_NODEVICE);
  559. }
  560. TRACEEXIT(("=%x\n", rc));
  561. return rc;
  562. } //SetBrightness