Eliot Graff
Microsoft Corporation
2003 年 4 月
适用于:
Microsoft Tablet PC Platform SDK
摘要:学习如何检测用户是以纵向方向还是横向方向查看 Tablet PC,并相应地调整应用程序。本文描述了检测用户何时在 Tablet PC 上切换纵向方向和横向方向的方法。这些 C#、Visual Basic .NET、C++ 和 Visual Basic 6.0 版的说明和示例都使用 Microsoft Tablet PC Platform SDK 版本 1.5 API。读者应该熟悉 Microsoft Tablet PC Platform SDK 和托管代码。(10 页打印页)
本页内容
简介
Tablet PC 的一个非常引人注意的功能就是用户既能以纵向方向工作又能以横向方向工作。目前,Microsoft 还没有关于用户更改屏幕方向频率的确定信息。使用性研究的确说明,用户选择方向取决于他们正在执行或刚刚执行完毕的任务。
要优化应用程序以便在 Tablet PC 上使用,应用程序应该既设计用于纵向方向也设计用于横向方向。当应用程序打开时,您可以检测使用的屏幕方向,并且可以检测用户何时切换屏幕方向。这可以使您相应地调整应用程序的显示。
要以托管代码或自动代码检测当前的屏幕方向,您要调用说明当前屏幕状态的方法。要以托管代码或自动代码检测屏幕旋转,您要侦听指出显示已更改的事件,然后调用说明当前屏幕状态的方法。在所有情况下,通过比较屏幕的高度和宽度,可确定用户是处于纵向方向还是处于横向方向。示例是以 C#、Microsoft Visual Basic .NET、C++ 和 Visual Basic 6.0 的形式提供的。
本文讨论如何检测:
-
Tablet PC 上的当前屏幕方向
-
用户何时在 Tablet PC 上切换纵向方向和横向方向
本文并不讨论以下内容:
-
优化应用程序以适用于纵向或横向查看
-
确定屏幕方向是主要还是次要
-
可视化设计准则
-
多个监视器
有关优化应用程序以适用于两种屏幕方向或确定屏幕方向是主要还是次要的详细信息,请参阅 Microsoft Tablet PC Platform SDK 版本 1.5 中的 。
有关可视化设计准则的详细信息,请参阅 Microsoft Tablet PC Platform SDK 版本 1.5 中的 。
有关多个监视器的详细信息,请参阅 MSDN Library 中的 。
如何检测当前屏幕方向
要检测当前屏幕方向,请调用屏幕高度和宽度的适当属性。比较高度和宽度来确定用户是以纵向方向还是以横向方向查看应用程序。
使用托管代码检测屏幕方向
在托管代码中,查找 对象的成员的 属性,它将返回一个类型。然后可以比较该矩形的高度和宽度。
C#
以下 C# 示例确定用户是以纵向方向还是以横向方向查看应用程序。
using System.Windows.Forms;
//. . .
//Set event handler
private void Form1_Load(object sender, System.EventArgs e)
{
int theScreenRectHeight = Screen.PrimaryScreen.Bounds.Height;
int theScreenRectWidth = Screen.PrimaryScreen.Bounds.Width;
//Compare height and width of screen and act accordingly.
if (theScreenRectHeight > theScreenRectWidth)
{
// Run the application in portrait, as in:
MessageBox.Text = "Run in portrait.";
}
else
{
// Run the application in landscape, as in:
MessageBox.Text = "Run in landscape.";
}
}
Visual Basic .NET
以下 Visual Basic .NET 示例确定用户是以纵向方向还是以横向方向查看应用程序。
Public Class Form1
Inherits System.Windows.Forms.Form
'. . .
'Set event handler
Private Sub Form1_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load
'Compare height and width of screen and act accordingly.
Dim theScreenHeight As Integer
Dim theScreenWidth As Integer
theScreenHeight = Screen.PrimaryScreen.Bounds.Height
theScreenWidth = Screen.PrimaryScreen.Bounds.Width
If (theScreenHeight > theScreenWidth) Then
'Run the application in portrait, as in:
MsgBox("Run in portrait", MsgBoxStyle.OKOnly, "Portrait")
Else
'Run the application in landscape, as in:
MsgBox("Run in landscape", MsgBoxStyle.OKOnly, "Landscape")
End If
使用 C++ 和 Visual Basic 6.0 检测屏幕方向
在自动代码中,请使用适当的函数来检索屏幕的高度和宽度。比较高度和宽度来确定用户是以纵向方向还是以横向方向查看应用程序。
C++
以下 C++ 示例确定用户是以纵向方向还是以横向方向查看应用程序,方法是使用 函数来检索整个屏幕的高度和宽度。
#include
//. . .
//Compare the height and width of the screen and act accordingly.
int theScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN);
int theScreenHeight = GetSystemMetrics(SM_CYFULLSCREEN);
if (theScreenWidth > theScreenHeight)
//Run the application in landscape, as in:
MessageBox(NULL,"Run in landscape.","Landscape",MB_OK);
else
//Run the application in portrait, as in:
MessageBox(NULL,"Run in portrait.","Portrait",MB_OK);
Visual Basic 6.0
以下 Visual Basic 6.0 示例确定用户是以纵向方向还是以横向方向查看应用程序,方法是返回 对象的 属性。
Private Sub Form_Load()
Dim theScreenWidth As Integer
Dim theScreenHeight As Integer
Dim iReturn As Integer
theScreenWidth = Screen.Width
theScreenHeight = Screen.Height
If (theScreenWidth > theScreenHeight) Then
'Run the application in landscape, as in:
iReturn = MsgBox("Run in landscape.", vbOKOnly, "Landscape")
Else
'Run the application in portrait, as in:
iReturn = MsgBox("Run in portrait.", vbOKOnly, "Portrait")
End If
End Sub
如何检测屏幕旋转
Microsoft .NET 框架 API 和 Win32 API 都允许您检测屏幕方向的变化。在托管代码中,请将事件处理程序分配给 类的 事件。
对于以 C++ 和 Visual Basic 6.0 编写的应用程序,通过将事件处理程序分配给 WM_DISPLAYCHANGE_win32_WM_DISPLAYCHANGE 消息来检测屏幕方向的变化。只要显示设置变化,您都要比较新屏幕的高度和宽度。如果高度大于宽度,应用程序则处于纵向方向;如果宽度大于高度,应用程序则处于横向方向。
使用托管代码检测屏幕旋转
使用托管代码检测屏幕旋转的特定方法是为 SystemEvents 类的 DisplaySettingsChanged 事件设置一个处理程序。然后附加一个事件处理程序以比较 Screen 对象的 Height 和 Width 属性,如前面的托管代码示例所示。
C#
以下 C# 示例说明如何检测用户何时更改了任何显示设置。然后,可以通过测试来检查用户是以纵向方向还是以横向方向查看应用程序,并相应地调整应用程序。
using System.Windows.Forms;
//. . .
//Set event handler
private void Form1_Load(object sender, System.EventArgs e)
{
Microsoft.Win32.SystemEvents.DisplaySettingsChanged +=
new System.EventHandler( displaySettingsChanged );
}
// Event handler for the system's DisplaySettingsChanged event.
// Detect and then compare the height and width of the screen.
private void displaySettingsChanged(object sender, EventArgs e)
{
Rectangle theScreenRect = Screen.GetBounds(this);
if( theScreenRect.Height > theScreenRect.Width )
{
//Run the application in portrait, as in:
MessageBox.Show("Run in portrait.");
}
else
{
//Run the application in landscape, as in:
MessageBox.Show("Run in landscape.");
}
}
Visual Basic .NET
以下 Visual Basic .NET 示例说明如何检测用户何时更改了任何显示设置。然后,可以通过测试来检查用户是以纵向方向还是以横向方向查看应用程序,并相应地调整应用程序。
Public Class Form1
Inherits System.Windows.Forms.Form
'. . .
'Create event handler to handle firing of DisplaySettingsChanged
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
AddHandler Microsoft.Win32.SystemEvents.DisplaySettingsChanged,
AddressOf DetectScreenRotation
End Sub
'Compare height and width of screen and take appropriate action
Public Sub DetectScreenRotation(ByVal sender As System.Object,
ByVal e As System.EventArgs)
Dim theScreenBounds As Rectangle
theScreenBounds = Screen.GetBounds(Screen.PrimaryScreen.Bounds)
If (theScreenBounds.Height > theScreenBounds.Width) Then
'Run the application in portrait, as in:
MsgBox("Run in portrait", MsgBoxStyle.OKOnly, "Portrait")
Else
'Run the application in landscape, as in:
MsgBox("Run in landscape", MsgBoxStyle.OKOnly, "Landscape")
End If
End Sub
使用 C++ 和 Visual Basic 6.0 检测屏幕旋转
C++
要检测以 C++ 编写的应用程序中的屏幕旋转,可以通过在 WindowProc 函数的 switch 语句中为 WM_DISPLAYCHANGE 消息设置一个用例来侦听 WM_DISPLAYCHANGE 消息。然后使用 WindowProc 函数中的 lParam 参数来检索整个屏幕的高度和宽度。以下 C++ 示例说明了这个过程。
#include
//. . .
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
// WM_DISPLAYCHANGE - determine screen orientatin and act accordingly
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
//. . .
//. . .
case WM_DISPLAYCHANGE:
{
//Separate the screen width and height and then
//check to see if screen width is greater than screen height
if ((int)lParam % 0x10000 > (int)lParam / 0x10000)
//Run the application in landscape, for example:
MessageBox(NULL,"Run in landscape.","Landscape",MB_OK);
else
//Run the application in portrait, as in:
MessageBox(NULL,"Run in portrait.","Portrait",MB_OK);
}
break;
Visual Basic 6.0
要检测以 Visual Basic 6.0 编写的应用程序的屏幕旋转,挂钩 WindowProc 函数以侦听 WM_DISPLAYCHANGE 消息。然后使用 WindowProc 函数中的 lParam 参数来检索整个屏幕的高度和宽度,如前面的 Visual Basic 6.0 示例所示。最后,解除挂钩,还原默认的 WindowProc 函数。以下 Visual Basic 6.0 示例说明了该过程。
窗体代码是:
Private Sub Form_Load()
gHW = Me.hwnd
Hook
End Sub
Private Sub Form_Terminate()
Unhook
End Sub
模块代码是:
Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias _
"SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Const GWL_WNDPROC = -4
Public Const WM_DISPLAYCHANGE = 126
Global lpPrevWndProc As Long
Global gHW As Long
Public Sub Hook()
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
AddressOf WindowProc)
End Sub
Public Sub Unhook()
Dim temp As Long
temp = SetWindowLong(gHW, GWL_WNDPROC, _
lpPrevWndProc)
End Sub
Function WindowProc(ByVal hw As Long, ByVal uMsg As _
Long, ByVal wParam As Long, ByVal lParam As Long) As _
Long
'Activated when display changes
If uMsg = WM_DISPLAYCHANGE Then
'Separate the width and height and then
'check to see if screen width is greater than screen height
If lParam Mod &H10000 > lParam \ &H10000 Then
'Run the application in landscape, for example:
MsgBox "Run in landscape."
Else
'Run the application in portrait, for example:
MsgBox "Run in portrait."
End If
End If
'Pass windows messages on to the default WindowProc
WindowProc = CallWindowProc(lpPrevWndProc, hw, _
uMsg, wParam, lParam)
End Function
