65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Mobile:实现 Kiosk 模式

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (6投票s)

2007年8月10日

CPOL

4分钟阅读

viewsIcon

73496

downloadIcon

993

Windows Mobile:实现 kiosk 模式

引言

Windows Mobile 是一个出色的生产力设备。但默认情况下,设备允许访问所有功能(电子邮件、联系人等),在特定场景下,您可能希望限制最终用户对其中某些功能的访问。

您将有两个选择:

  • 集成到标准 Shell 中
  • 自定义系统为 Kiosk 模式

我将重点介绍第二种选择。为了将系统设置为 Kiosk 模式,我们将不得不:

  • 编写一个具有屏幕的应用程序,该屏幕将像“Today”屏幕一样工作。
  • 控制硬件按钮以限制对 Windows Mobile 功能的访问。
  • 当然,还要让应用程序在启动时运行。
  • 这是一个不完整的列表……

背景

我不会专注于 Compact Framework 开发和操作系统底层库的交互。但请记住 .NET Compact Framework 架构。

  • 框架
  • 公共语言运行时
  • Windows CE

这样您就能理解为什么我们引用 microsoft.windowsce.forms 来进行底层功能调用。

我还使用了 OpenNETCF www.openNETCF.com 来读取/写入注册表。该库在其网站上已得到全面解释。

Using the Code

我们的第一个任务是使用 Visual Studio 创建一个新的 Smart Device 项目。如引言中所述,我们将设置默认窗体 Form1.cs 的属性,以创建一个类似“Today”的屏幕。您可以通过属性窗口或代码来完成。

public frmKiosk()
{
    InitializeComponent();

    ControlBox = false;
    FormBorderStyle = FormBorderStyle.None;
    MaximizeBox = false;
    MinimizeBox = false;
    WindowState = FormWindowState.Maximized;
}

现在,我们将不得不控制硬件按钮。这是通过 Microsoft.WindowsCE.Form.MessageWindows 来完成的。此类允许我们拦截 Windows 消息并决定如何处理它们(内部例程、向其他类引发事件,或者……什么都不做)。这将允许我们拦截由硬件按钮发送的消息,并简单地决定不响应它们!

逻辑非常简单:

  • 创建一个继承自 MessageWindows 的类。重写 WndProc 方法来捕获窗口消息并实现我们自己的业务逻辑。我们将仅拦截 HOTKEY 消息,但相同的代码也可用于处理所有类型的窗口消息(完整列表可在 http:\\www.pinvoke.net 上找到)。
  • 取消注册硬件按钮:默认情况下,硬件按钮引发的消息由默认进程处理。
  • 注册硬件按钮:硬件按钮引发的消息将由我们的自定义 MessageWindows 处理。

我们的自定义 MessageWindows 的代码将如下所示:

public class internalMessageWindow : MessageWindow
{
        // Which message type ?
        public const int WM_HOTKEY = 0x0312;

        Form referedForm;

        public internalMessageWindow(Form referedForm)
        {
            this.referedForm = referedForm;
        }

        protected override void WndProc(ref Message msg)
        {
            switch (msg.Msg)
            {
                case WM_HOTKEY:
                    // Do no reply to this key ...
                    return;
            }
            base.WndProc(ref msg);
        }
}

现在,我们需要将我们的窗体与自定义的 WindowsMessage 关联起来。

FormCode
{    
    internalMessageWindow messageWindow;
    public Form Constructor()
    {
        this.messageWindow = new internalMessageWindow(this); 
    }        
}

并使用 coredll.dll 中的 UnregisterFunc1RegisterRecordKey 来取消注册/注册硬件按钮(有关签名详细信息,请参阅 http:\\www.pinvoke.net)。

FormCode
{    
    public Form Constructor()
    {
        ...
        RegisterHKeys.RegisterRecordKey(this.messageWindow.Hwnd);
    }        
}
public class RegisterHKeys
    {
        [DllImport("coredll.dll", SetLastError = true)]
        public static extern bool RegisterHotKey
        ...
        and
        private static extern bool UnregisterFunc1
        ...
        
        public static void RegisterRecordKey(IntPtr hWnd)
        {
            UnregisterFunc1(KeyModifiers.Windows, (int)KeysHardware.Hardware1);
            RegisterHotKey(hWnd, (int)KeysHardware.Hardware1, 
		KeyModifiers.Windows, (int)KeysHardware.Hardware1);
            
            // Repeat for every single hardware button you wan to handle
        }
    }

现在,我们需要强制我们的应用程序在每次 Windows Mobile 启动时都运行。这可以通过 coredll.dll 库的 CeRunAppAtEvent 函数来实现。此函数允许将应用程序链接到设备的特定事件。在我们的上下文中,我们将应用程序链接到 Wakeup 事件。这意味着每次设备启动时,都会引发 Wakeup 事件,并且由于我们将应用程序与此事件链接,我们的应用程序将启动。

要将应用程序链接到事件,我们将使用以下代码:

Win32.CeRunAppAtEvent(_kioskName, NotificationEvent.Wakeup);

我们将使用以下代码来“解除”应用程序/事件的链接:

Win32.CeRunAppAtEvent(_kioskName, NotificationEvent.None);

因此,现在我们有了一个启动页面,它会在设备启动时出现。我们还捕获了按钮事件以禁用硬件交互。最后一步是允许最终用户启动特定应用程序,并等待该应用程序关闭后再返回我们的启动页面。

这是一个相当简单的步骤,使用 ProcessStartInfo 类。这将允许我们在新进程中启动一个应用程序,并将当前应用程序置于等待状态,等待特定进程退出。

要启动新进程,我们将使用以下代码,它将返回进程句柄:

private static Process LaunchApp(string filename)
{
    ProcessStartInfo s = new ProcessStartInfo();
    s.FileName = filename;
    s.UseShellExecute = true;
    return Process.Start(s);
}

我们只需添加例程来启动应用程序,等待进程退出,使用此代码:

private void but_Click(object sender, EventArgs e)
{
    this.Hide();
    Process ela = LaunchApp(application2);
    ela.WaitForExit();
    this.Show();
}

需要注意的事项:

  • 未处理设备的硬重置。进行硬重置将取消应用程序与 Wakeup 事件的订阅。
  • 此解决方案不可移植!窗体是为特定分辨率(本示例中为 240x320)和具有默认四个硬件按钮的设备设计的。安装在具有其他规格的设备上将失败。

操作指南

处理非标准硬件按钮

本示例基于具有四个按钮的默认设备。如果您的目标设备有更多按钮,或者 MessageWindow 未捕获按钮交互,您将需要验证您的按钮代码。使用注册表编辑器(远程注册表编辑器)并转到 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shell\Keys\。您将看到多个“文件夹”,对应于您的硬件键,例如 40C1、40C2 等。将最后两个字母转换为十进制,您将获得按钮键(C1=193,C2=194,...)。

结论

此示例远非生产产品,但表明处理 PocketPC 等特定设备相当容易。与此类硬件交互需要一点 pinvoke,因为 compact framework 封装了部分但并非全部功能。欢迎任何评论/建议。

参考

历史

  • 2007/10/08:发布到 CodeProject
© . All rights reserved.