660 lines
18 KiB
C
660 lines
18 KiB
C
/*++
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
display.c
|
|
|
|
Abstract: Tablet PC Display Property Sheet module.
|
|
|
|
Environment:
|
|
User mode
|
|
|
|
Author:
|
|
Michael Tsang (MikeTs) 14-Jun-2000
|
|
|
|
Revision History:
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
#define BRIGHTSCALE_MIN 0
|
|
#define BRIGHTSCALE_MAX 15
|
|
|
|
#define BRIGHTSCALE_LO 1
|
|
#define BRIGHTSCALE_HI 15
|
|
|
|
HANDLE ghBackLight = INVALID_HANDLE_VALUE;
|
|
HMODULE ghmodSMAPI = NULL;
|
|
FARPROC gpfnCallSMAPI = NULL;
|
|
ERRMAP SMAPIErrMap[] =
|
|
{
|
|
RT_ERR_INSTRETCHMODE, IDSERR_SMAPI_INSTRETCHMODE,
|
|
RT_ERR_INDUALAPPMODE, IDSERR_SMAPI_INDUALAPPMODE,
|
|
RT_ERR_INDUALVIEWMODE, IDSERR_SMAPI_INDUALVIEWMODE,
|
|
RT_ERR_INRGBPROJMODE, IDSERR_SMAPI_INRGBPROJMODE,
|
|
RT_ERR_INVIRTUALSCREEN, IDSERR_SMAPI_INVIRTUALSCREEN,
|
|
RT_ERR_INVIRTUALREFRESH, IDSERR_SMAPI_INVIRTUALREFRESH,
|
|
RT_ERR_INROTATEMODE, IDSERR_SMAPI_INROTATEMODE,
|
|
RT_ERR_2NDMONITORON, IDSERR_SMAPI_2NDMONITORON,
|
|
RT_ERR_WRONGHW, IDSERR_SMAPI_WRONGHW,
|
|
RT_ERR_CLRDEPTH, IDSERR_SMAPI_CLRDEPTH,
|
|
RT_ERR_MEMORY, IDSERR_SMAPI_MEMORY,
|
|
RT_ERR_SETMODE, IDSERR_SMAPI_SETMODE,
|
|
RT_ERR_DIRECTION, IDSERR_SMAPI_DIRECTION,
|
|
RT_ERR_CAPTUREON, IDSERR_SMAPI_CAPTUREON,
|
|
RT_ERR_VIDEOON, IDSERR_SMAPI_VIDEOON,
|
|
RT_ERR_DDRAWON, IDSERR_SMAPI_DDRAWON,
|
|
RT_ERR_ALREADYSET, IDSERR_SMAPI_ALREADYSET,
|
|
0, 0
|
|
};
|
|
|
|
SMBLITE_BRIGHTNESS gBrightness = {0};
|
|
BOOL gfPortraitMode = FALSE;
|
|
DWORD gDisplayHelpIDs[] =
|
|
{
|
|
IDC_ROTATE_GROUPBOX, IDH_ROTATE,
|
|
0, 0
|
|
};
|
|
|
|
/*++
|
|
@doc EXTERNAL
|
|
|
|
@func INT_PTR | DisplayDlgProc |
|
|
Dialog procedure for the display page.
|
|
|
|
@parm IN HWND | hwnd | Window handle.
|
|
@parm IN UINT | uMsg | Message.
|
|
@parm IN WPARAM | wParam | Word Parameter.
|
|
@parm IN LPARAM | lParam | Long Parameter.
|
|
|
|
@rvalue Return value depends on the message.
|
|
--*/
|
|
|
|
INT_PTR APIENTRY
|
|
DisplayDlgProc(
|
|
IN HWND hwnd,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
TRACEPROC("DisplayDlgProc", 2)
|
|
INT_PTR rc = FALSE;
|
|
static BOOL fPortrait = FALSE;
|
|
static SMBLITE_BRIGHTNESS Brightness = {0};
|
|
|
|
TRACEENTER(("(hwnd=%p,Msg=%s,wParam=%x,lParam=%x)\n",
|
|
hwnd, LookupName(uMsg, WMMsgNames) , wParam, lParam));
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
rc = InitDisplayPage(hwnd);
|
|
if (rc)
|
|
{
|
|
fPortrait = gfPortraitMode;
|
|
Brightness = gBrightness;
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(hwnd, FALSE);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
if (ghmodSMAPI != NULL)
|
|
{
|
|
FreeLibrary(ghmodSMAPI);
|
|
ghmodSMAPI = NULL;
|
|
gpfnCallSMAPI = NULL;
|
|
}
|
|
|
|
if (ghBackLight != INVALID_HANDLE_VALUE)
|
|
{
|
|
if ((Brightness.bACValue != gBrightness.bACValue) ||
|
|
(Brightness.bDCValue != gBrightness.bDCValue))
|
|
{
|
|
//
|
|
// User must have canceled the setting, so restore
|
|
// brightness to the original values.
|
|
//
|
|
SetBrightness(&gBrightness, FALSE);
|
|
}
|
|
|
|
CloseHandle(ghBackLight);
|
|
ghBackLight = INVALID_HANDLE_VALUE;
|
|
}
|
|
break;
|
|
|
|
case WM_DISPLAYCHANGE:
|
|
gfPortraitMode = (LOWORD(lParam) < HIWORD(lParam));
|
|
CheckRadioButton(hwnd,
|
|
IDC_ROTATE_LANDSCAPE,
|
|
IDC_ROTATE_PORTRAIT,
|
|
gfPortraitMode? IDC_ROTATE_PORTRAIT:
|
|
IDC_ROTATE_LANDSCAPE);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
NMHDR FAR *lpnm = (NMHDR FAR *)lParam;
|
|
|
|
switch (lpnm->code)
|
|
{
|
|
case PSN_APPLY:
|
|
{
|
|
if (fPortrait ^ gfPortraitMode)
|
|
{
|
|
DWORD smrc;
|
|
|
|
smrc = RotateScreen(fPortrait? RT_CLOCKWISE: 0);
|
|
if (smrc == SMAPI_OK)
|
|
{
|
|
gfPortraitMode = fPortrait;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwErr = MapError(smrc, SMAPIErrMap, FALSE);
|
|
|
|
CheckRadioButton(hwnd,
|
|
IDC_ROTATE_LANDSCAPE,
|
|
IDC_ROTATE_PORTRAIT,
|
|
gfPortraitMode?
|
|
IDC_ROTATE_PORTRAIT:
|
|
IDC_ROTATE_LANDSCAPE);
|
|
if (dwErr == 0)
|
|
{
|
|
ErrorMsg(IDSERR_SMAPI_CALLFAILED, smrc);
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg(dwErr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((Brightness.bACValue != gBrightness.bACValue) ||
|
|
(Brightness.bDCValue != gBrightness.bDCValue))
|
|
{
|
|
//
|
|
// User has committed to the new values, save them.
|
|
//
|
|
if (SetBrightness(&Brightness, TRUE))
|
|
{
|
|
gBrightness = Brightness;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_ROTATE_LANDSCAPE:
|
|
fPortrait = FALSE;
|
|
goto CheckRotation;
|
|
|
|
case IDC_ROTATE_PORTRAIT:
|
|
fPortrait = TRUE;
|
|
|
|
CheckRotation:
|
|
if ((HIWORD(wParam) == BN_CLICKED) &&
|
|
!IsDlgButtonChecked(hwnd, LOWORD(wParam)))
|
|
{
|
|
//
|
|
// Rotation has changed, mark the property
|
|
// sheet dirty.
|
|
//
|
|
CheckRadioButton(hwnd,
|
|
IDC_ROTATE_LANDSCAPE,
|
|
IDC_ROTATE_PORTRAIT,
|
|
LOWORD(wParam));
|
|
SendMessage(GetParent(hwnd),
|
|
PSM_CHANGED,
|
|
(WPARAM)hwnd,
|
|
0);
|
|
rc = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
#ifdef BACKLIGHT
|
|
case WM_HSCROLL:
|
|
{
|
|
UCHAR BrightScale;
|
|
|
|
BrightScale = (UCHAR)SendDlgItemMessage(hwnd,
|
|
IDC_BRIGHTNESS_AC,
|
|
TBM_GETPOS,
|
|
0,
|
|
0);
|
|
Brightness.bACValue = BrightScale*(BRIGHTNESS_MAX + 1)/
|
|
(BRIGHTSCALE_MAX + 1);
|
|
BrightScale = (UCHAR)SendDlgItemMessage(hwnd,
|
|
IDC_BRIGHTNESS_DC,
|
|
TBM_GETPOS,
|
|
0,
|
|
0);
|
|
Brightness.bDCValue = BrightScale*(BRIGHTNESS_MAX + 1)/
|
|
(BRIGHTSCALE_MAX + 1);
|
|
|
|
if ((Brightness.bACValue != gBrightness.bACValue) ||
|
|
(Brightness.bDCValue != gBrightness.bDCValue))
|
|
{
|
|
if (SetBrightness(&Brightness, FALSE))
|
|
{
|
|
SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
case WM_HELP:
|
|
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
TEXT("tabletpc.hlp"),
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)gDisplayHelpIDs);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND)wParam,
|
|
TEXT("tabletpc.hlp"),
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)gDisplayHelpIDs);
|
|
break;
|
|
}
|
|
|
|
TRACEEXIT(("=%x\n", rc));
|
|
return rc;
|
|
} //DisplayDlgProc
|
|
|
|
/*++
|
|
@doc INTERNAL
|
|
|
|
@func BOOL | InitDisplayPage |
|
|
Initialize the display property page.
|
|
|
|
@parm IN HWND | hwnd | Window handle.
|
|
|
|
@rvalue SUCCESS | Returns TRUE.
|
|
@rvalue FAILURE | Returns FALSE.
|
|
--*/
|
|
|
|
BOOL
|
|
InitDisplayPage(
|
|
IN HWND hwnd
|
|
)
|
|
{
|
|
TRACEPROC("InitDisplayPage", 2)
|
|
BOOL rc = FALSE;
|
|
|
|
TRACEENTER(("(hwnd=%x)\n", hwnd));
|
|
|
|
#ifdef BACKLIGHT
|
|
SendDlgItemMessage(hwnd,
|
|
IDC_BRIGHTNESS_AC,
|
|
TBM_SETRANGE,
|
|
TRUE,
|
|
MAKELONG(BRIGHTSCALE_LO, BRIGHTSCALE_HI));
|
|
SendDlgItemMessage(hwnd,
|
|
IDC_BRIGHTNESS_DC,
|
|
TBM_SETRANGE,
|
|
TRUE,
|
|
MAKELONG(BRIGHTSCALE_LO, BRIGHTSCALE_HI));
|
|
#endif
|
|
ghmodSMAPI = LoadLibrary(TEXT("smhook.dll"));
|
|
if (ghmodSMAPI != NULL)
|
|
{
|
|
gpfnCallSMAPI = GetProcAddress(ghmodSMAPI, "CallSMAPI");
|
|
|
|
if (gpfnCallSMAPI != NULL)
|
|
{
|
|
LONG cxScreen, cyScreen;
|
|
|
|
cxScreen = GetSystemMetrics(SM_CXSCREEN);
|
|
cyScreen = GetSystemMetrics(SM_CYSCREEN);
|
|
gfPortraitMode = (cxScreen < cyScreen);
|
|
CheckRadioButton(hwnd,
|
|
IDC_ROTATE_LANDSCAPE,
|
|
IDC_ROTATE_PORTRAIT,
|
|
gfPortraitMode? IDC_ROTATE_PORTRAIT:
|
|
IDC_ROTATE_LANDSCAPE);
|
|
|
|
#ifdef BACKLIGHT
|
|
ghBackLight = CreateFile(SMBLITE_IOCTL_DEVNAME,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (ghBackLight == INVALID_HANDLE_VALUE)
|
|
{
|
|
ErrorMsg(IDSERR_SMBLITE_OPENDEV, GetLastError());
|
|
}
|
|
else if (GetBrightness(&gBrightness))
|
|
{
|
|
LPARAM lParam;
|
|
|
|
lParam = gBrightness.bACValue*(BRIGHTSCALE_MAX + 1)/
|
|
(BRIGHTNESS_MAX + 1);
|
|
SendDlgItemMessage(hwnd,
|
|
IDC_BRIGHTNESS_AC,
|
|
TBM_SETPOS,
|
|
TRUE,
|
|
lParam);
|
|
lParam = gBrightness.bDCValue*(BRIGHTSCALE_MAX + 1)/
|
|
(BRIGHTNESS_MAX + 1);
|
|
SendDlgItemMessage(hwnd,
|
|
IDC_BRIGHTNESS_DC,
|
|
TBM_SETPOS,
|
|
TRUE,
|
|
lParam);
|
|
}
|
|
#endif
|
|
|
|
rc = TRUE;
|
|
}
|
|
else
|
|
{
|
|
FreeLibrary(ghmodSMAPI);
|
|
ghmodSMAPI = NULL;
|
|
ErrorMsg(IDSERR_GETPROCADDR_SMAPI);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg(IDSERR_LOADLIBRARY_SMAPI);
|
|
}
|
|
|
|
TRACEEXIT(("=%x\n", rc));
|
|
return rc;
|
|
} //InitDisplayPage
|
|
|
|
/*++
|
|
@doc EXTERNAL
|
|
|
|
@func DWORD | SetRotation | Set display rotation mode.
|
|
|
|
@parm IN DWORD | dwRotation | Specified the rotation.
|
|
|
|
@rvalue SUCCESS | Returns TRUE.
|
|
@rvalue FAILURE | Returns FALSE.
|
|
--*/
|
|
|
|
BOOL
|
|
__stdcall
|
|
SetRotation(
|
|
IN DWORD dwRotation
|
|
)
|
|
{
|
|
TRACEPROC("SetRotation", 2)
|
|
BOOL rc = FALSE;
|
|
BOOL fNeedUnload = FALSE;
|
|
|
|
TRACEENTER(("(Rotation=%x)\n", dwRotation));
|
|
|
|
if (gpfnCallSMAPI == NULL)
|
|
{
|
|
ghmodSMAPI = LoadLibrary(TEXT("smhook.dll"));
|
|
if (ghmodSMAPI != NULL)
|
|
{
|
|
gpfnCallSMAPI = GetProcAddress(ghmodSMAPI, "CallSMAPI");
|
|
|
|
if (gpfnCallSMAPI != NULL)
|
|
{
|
|
fNeedUnload = TRUE;
|
|
}
|
|
else
|
|
{
|
|
FreeLibrary(ghmodSMAPI);
|
|
ghmodSMAPI = NULL;
|
|
ErrorMsg(IDSERR_GETPROCADDR_SMAPI);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg(IDSERR_LOADLIBRARY_SMAPI);
|
|
}
|
|
}
|
|
|
|
if (gpfnCallSMAPI != NULL)
|
|
{
|
|
DWORD smrc, dwErr;
|
|
|
|
smrc = RotateScreen(dwRotation);
|
|
if (smrc == SMAPI_OK)
|
|
{
|
|
rc = TRUE;
|
|
}
|
|
else
|
|
{
|
|
dwErr = MapError(smrc, SMAPIErrMap, FALSE);
|
|
if (dwErr == 0)
|
|
{
|
|
ErrorMsg(IDSERR_SMAPI_CALLFAILED, smrc);
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg(dwErr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fNeedUnload)
|
|
{
|
|
gpfnCallSMAPI = NULL;
|
|
FreeLibrary(ghmodSMAPI);
|
|
ghmodSMAPI = NULL;
|
|
}
|
|
|
|
TRACEEXIT(("=%x\n", rc));
|
|
return rc;
|
|
} //SetRotation
|
|
|
|
/*++
|
|
@doc INTERNAL
|
|
|
|
@func DWORD | RotateScreen |
|
|
Rotate the screen to the given orientation.
|
|
|
|
@parm IN DWORD | dwRotation | Specified the rotation.
|
|
|
|
@rvalue SUCCESS | Returns SMAPI_OK.
|
|
@rvalue FAILURE | Returns SMAPI error code.
|
|
--*/
|
|
|
|
DWORD
|
|
RotateScreen(
|
|
IN DWORD dwRotation
|
|
)
|
|
{
|
|
TRACEPROC("RotateScreen", 2)
|
|
DWORD rc;
|
|
|
|
TRACEENTER(("(Rotation=%d)\n", dwRotation));
|
|
|
|
if (gpfnCallSMAPI != NULL)
|
|
{
|
|
if (dwRotation == 0)
|
|
{
|
|
rc = gpfnCallSMAPI(ROTATE_EXIT, 0, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
if (gpfnCallSMAPI(ROTATE_STATUS, 0, 0, 0))
|
|
{
|
|
gpfnCallSMAPI(ROTATE_EXIT, 0, 0, 0);
|
|
}
|
|
|
|
rc = gpfnCallSMAPI(ROTATE_INIT, dwRotation, 0, 0);
|
|
if (rc == SMAPI_OK)
|
|
{
|
|
//
|
|
// The SMI driver has this dynamic mode table feature that
|
|
// it may not report portrait display modes unless we
|
|
// enumerate them. Therefore, we do display mode enumeration
|
|
// just to force the SMI driver to load a display mode tablet
|
|
// that support portrait modes.
|
|
//
|
|
EnumDisplayModes();
|
|
rc = gpfnCallSMAPI(ROTATE_EXECUTE, NULL, dwRotation, 0);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = SMAPI_ERR_NODRV;
|
|
}
|
|
|
|
TRACEEXIT(("=%x\n", rc));
|
|
return rc;
|
|
} //RotateScreen
|
|
|
|
/*++
|
|
@doc INTERNAL
|
|
|
|
@func VOID | EnumDisplayModes | Enumerate display modes to force
|
|
SMI driver to dynamically load a mode table that supports
|
|
Portrait modes.
|
|
|
|
@parm None.
|
|
|
|
@rvalue None.
|
|
--*/
|
|
|
|
VOID
|
|
EnumDisplayModes(
|
|
VOID
|
|
)
|
|
{
|
|
TRACEPROC("EnumDisplayModes", 3)
|
|
DWORD i;
|
|
DEVMODE DevMode;
|
|
|
|
TRACEENTER(("()\n"));
|
|
|
|
for (i = 0; EnumDisplaySettings(NULL, i, &DevMode); ++i)
|
|
{
|
|
//
|
|
// Don't have to do anything.
|
|
//
|
|
}
|
|
|
|
TRACEEXIT(("!\n"));
|
|
return;
|
|
} //EnumDisplayModes
|
|
|
|
/*++
|
|
@doc INTERNAL
|
|
|
|
@func BOOL | GetBrightness | Call the backlight driver to get
|
|
LCD brightness.
|
|
|
|
@parm OUT PSMBLITE_BRIGHTNESS | Brightness | Brightness values.
|
|
|
|
@rvalue SUCCESS | Returnes TRUE.
|
|
@rvalue FAILURE | Returnes FALSE.
|
|
--*/
|
|
|
|
BOOL
|
|
GetBrightness(
|
|
OUT PSMBLITE_BRIGHTNESS Brightness
|
|
)
|
|
{
|
|
TRACEPROC("GetBrightness", 3)
|
|
BOOL rc = FALSE;
|
|
|
|
TRACEENTER(("(Brightness=%p)\n", Brightness));
|
|
|
|
if (ghBackLight != INVALID_HANDLE_VALUE)
|
|
{
|
|
DWORD dwcbReturned;
|
|
|
|
rc = DeviceIoControl(ghBackLight,
|
|
IOCTL_SMBLITE_GETBRIGHTNESS,
|
|
NULL,
|
|
0,
|
|
Brightness,
|
|
sizeof(*Brightness),
|
|
&dwcbReturned,
|
|
NULL);
|
|
if (rc == FALSE)
|
|
{
|
|
ErrorMsg(IDSERR_SMBLITE_DEVIOCTL, GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg(IDSERR_SMBLITE_NODEVICE);
|
|
}
|
|
|
|
TRACEEXIT(("=%x (AC=%d,DC=%d)\n",
|
|
rc, Brightness->bACValue, Brightness->bDCValue));
|
|
return rc;
|
|
} //GetBrightness
|
|
|
|
/*++
|
|
@doc INTERNAL
|
|
|
|
@func BOOL | SetBrightness | Call the backlight driver to set
|
|
LCD brightness.
|
|
|
|
@parm IN PSMBLITE_BRIGHTNESS | Brightness | Brightness values.'
|
|
@parm IN BOOLEAN | fSaveSettings | If TRUE, save new brightness in the
|
|
registry.
|
|
|
|
@rvalue SUCCESS | Returnes TRUE.
|
|
@rvalue FAILURE | Returnes FALSE.
|
|
--*/
|
|
|
|
BOOL
|
|
SetBrightness(
|
|
IN PSMBLITE_BRIGHTNESS Brightness,
|
|
IN BOOLEAN fSaveSettings
|
|
)
|
|
{
|
|
TRACEPROC("SetBrightness", 3)
|
|
BOOL rc = FALSE;
|
|
|
|
TRACEENTER(("(Brightness=%p,ACValue=%d,DCValue=%d)\n",
|
|
Brightness, Brightness->bACValue, Brightness->bDCValue));
|
|
|
|
if (ghBackLight != INVALID_HANDLE_VALUE)
|
|
{
|
|
SMBLITE_SETBRIGHTNESS SetLCD;
|
|
DWORD dwcbReturned;
|
|
|
|
SetLCD.Brightness = *Brightness;
|
|
SetLCD.fSaveSettings = fSaveSettings;
|
|
rc = DeviceIoControl(ghBackLight,
|
|
IOCTL_SMBLITE_SETBRIGHTNESS,
|
|
&SetLCD,
|
|
sizeof(SetLCD),
|
|
NULL,
|
|
0,
|
|
&dwcbReturned,
|
|
NULL);
|
|
if (rc == FALSE)
|
|
{
|
|
ErrorMsg(IDSERR_SMBLITE_DEVIOCTL, GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ErrorMsg(IDSERR_SMBLITE_NODEVICE);
|
|
}
|
|
|
|
TRACEEXIT(("=%x\n", rc));
|
|
return rc;
|
|
} //SetBrightness
|