布局设计 在Smartphone 2002屏幕上放置控件最主要的规则是“一个控件应该占据一行”。建议你使用标签来表示控件中所显示何种类型的信息。标签应该直接放置在控件的上方。
控件 根据Smartphone 2002的指导方针,列表框应该只包括一行。浏览可以用两种方法实现:使用一个带有左/右按钮的微调控件以及使用列表的展开视图。列表的展开视图在我们这种情况下非常有用,因为列表中会拥有很多的项目。
在Smartphone 2002平台下是不支持按钮的,一个好的解决方法是将它们替换为菜单条上的菜单项。
菜单条的动作按钮(左边的软键)将代替鼠标的点击。用户将使用这个键来进入注册表的键中。第二个软键通常用于菜单,但是我们现在这个简单的应用程序中还没有菜单。因此,在菜单条中我们还需要另外一个键:“回退”项来代替原应用程序的“回退/向上”按钮。
行为 通常,应用程序的用户界面是依赖于鼠标(手写笔)事件的。Smartphone 2002则并不会有产生点击事件的机会,因为它没有触摸屏。在我们这种情况下,我们拥有一个非常简单的应用程序,但在没有触摸屏的情况下它是无法工作的!问题就在于列表框是利用点击来浏览的。我们将使用菜单条中特殊的菜单项来代替这些点击。
实现可扩展的列表框和编辑框
我们需要减少列表框的高度,并添加微调控件来实现项目的选择和扩展。以下的资源代码根据这些需求创建了一个列表框资源。
LISTBOX IDL_LISTBOX,4,15,131,10,
WS_TABSTOP | WS_VISIBLE | LBS_NOINTEGRALHEIGHT
CONTROL "", IDC_UPDOWN, UPDOWN_CLASS,
WS_VISIBLE | UDS_AUTOBUDDY | UDS_HORZ | UDS_ALIGNRIGHT |
UDS_ARROWKEYS | UDS_SETBUDDYINT | UDS_WRAP | UDS_EXPANDABLE,
0,0,0,0
以下的资源代码创建了一个可扩展的编辑框,因为这是一个查看工具应用程序,所以使用了只读的标记。
EDITTEXT IDE_TEXTOUT,4,70,131,12,ES_MULTILINE | ES_AUTOVSCROLL |
ES_AUTOHSCROLL | ES_READONLY | WS_TABSTOP
CONTROL "", IDC_UPDOWN, UPDOWN_CLASS, UDS_AUTOBUDDY |
UDS_ALIGNRIGHT | UDS_EXPANDABLE | UDS_NOSCROLL,
0, 0, 0, 0
菜单条 菜单条资源是一种新的资源,并且资源编辑器不能够正确地处理它。关于菜单条资源,已知的两个问题是:一个未定义的I_IMAGENONE关键字,以及资源编辑器将菜单条资源转换为二进制格式。
为了解决这些问题,我将菜单条资源放到了一个单独的自定义资源文件之中。要这么做,我创建了一个单独的文本文件,并添加了以下的菜单条代码。
IDR_MENUBAR RCDATA
BEGIN
IDR_MAINMENU,
2,
I_IMAGENONE, IDM_ENTER, TBSTATE_ENABLED,
TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE, IDS_ENTER, 0, NOMENU,
I_IMAGENONE, IDM_BACK, TBSTATE_ENABLED,
TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE, IDS_BACK, 0, NOMENU,
END
然后我将文件保存为PSPCMonkey.rc2,并将其添加入工程。最后的一步是使用View->Resource Includes菜单项,在compile time resource includes中包含这个文件。
这个方法使用自定义资源解决了这一问题。现在菜单条资源不能在资源编辑器中编辑,它应该作为一个文本文件来编辑。
同样,我们需要在字串表中添加用于菜单条显示的字符串,就像下面这样。
STRINGTABLE DISCARDABLE
BEGIN
IDS_BACK "Back"
IDS_ENTER "Enter"
END
回退键 回退键应该使用户返回前一个屏幕。在编辑控件中,它还要作为退格键来使用。在我们的应用程序中所有的编辑框都是只读的,因此,在主窗口按下回退键应该隐藏我们的应用程序。我推荐你每一次应用程序执行的时候都使用户返回到一个“更新”的状态。那么,回退键应该关闭我们的对话框。
要实现这一行为,我们不应该在我们的对话框中改写回退键。在这种情况下,回退键应该向对话框发送WM_COMMAND/IDCANCEL消息。我们只需要向DialogProc的主switch之中添加标准的处理器。
...
case WM_COMMAND:
switch (LOWORD(wParam))
{
// 用户选择了关闭对话框
case IDCANCEL: // 处理回退键
EndDialog(hDlg, TRUE);
break;
...
标题条 由于任务栏的尺寸有限,应用程序的标题应该尽可能地简洁明了。而且,标题可以根据子窗口来更换。例如,一个消息框将在标题条显示它的标题。在我们的应用程序中,标题条在主窗口的情况显示“Registry Editor”,在错误信息的消息框情况下显示“Error”。
标签 标准的Smartphone 2002应用程序(例如,收件箱)为标签使用了11号加粗的Nina,而不是当前对话框的字体。以下的代码创建了这一字体。
HFONT CreateLabelFont()
{
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
HDC hdc = ::GetDC(NULL);
lf.lfHeight = -11 * GetDeviceCaps(hdc, LOGPIXELSY) / 72;
::ReleaseDC(NULL, hdc);
lf.lfWeight = FW_SEMIBOLD;
return CreateFontIndirect(&lf);
}
现在我们就可以在WM_INITDIALOG消息处理器中将这个创建好的字体指派给各个标签了。
g_hLabelFont = CreateLabelFont();
::SendDlgItemMessage(hDlg, IDC_STATIC1, WM_SETFONT, (int) g_hLabelFont, 0);
::SendDlgItemMessage(hDlg, IDC_STATIC2, WM_SETFONT, (int) g_hLabelFont, 0);
::SendDlgItemMessage(hDlg, IDC_STATIC3, WM_SETFONT, (int) g_hLabelFont, 0);
::SendDlgItemMessage(hDlg, IDC_STATIC4, WM_SETFONT, (int) g_hLabelFont, 0);
并且,当不再需要这个字体的时候(在WM_DESTROY处理器中)销毁它。
case WM_DESTROY:
DeleteObject(g_hLabelFont);
break;
总结 从编译器的观点来看,将一个没有使用MFC的Windows CE应用程序移植到Smartphone 2002平台是很简单的。但是,移植并不是这么简单的。你最主要的努力将会花费在用户界面的设计上。你应该为这个小屏幕来设计你的窗口;考虑这些不能使用鼠标点击的新控件、新行为,回退键以及标题条。
看起来,大多数的应用程序都应该保证它们的可用性。我们失去了触摸屏、大屏幕以及一些控件,但是我们得到了可扩展的列表框和编辑框、微调控件、可滚动的对话框以及很多的硬件按键。我认为这些新的方面应该可以补偿这些失去的东西,在Smartphone 2002平台的应用程序上发挥作用。