SmartDevice应用程序的自定义消息过滤器

时间:2010-03-30 07:54:56

标签: c# windows-mobile compact-framework

Since Compact Framework calls Show() on the form passed to Application.Run(),我决定创建自己的消息泵。

我不知道我该怎么做。

任何帮助(如一个简单的例子)将不胜感激。

3 个答案:

答案 0 :(得分:2)

我发现这是一个比预期的Windows窗体应用程序更大的问题。对于我的解决方案,我从三个不同的网站上提取建议,发现这个解决方案非常有效。根据我的需要,我有一个Windows服务,在系统托盘中有一个UI控制器组件。只需托盘图标和图标的上下文菜单,UI就需要启动最小化。 UI在激活时作为模态对话框运行,允许用户在后台线程上启动长时间运行的进程,一旦启动,UI需要恢复用户的响应。

在Windows Form类的构造函数中,我设置了ControlBox并禁用了最小化和最大化按钮:

public SystemTrayApp()
{
    InitializeComponent();
    this.Visible = false;
    // Hide Maximize and Minimize buttons on form
    this.StartPosition = FormStartPosition.CenterScreen;
    this.MaximizeBox = false;
    this.MinimizeBox = false;
}

需要启用ControlBox以允许用户在屏幕上移动对话框但不更改大小,禁用表单关闭按钮,表单右上角的红色X,我使用:

// Force form close button to be disabled
private const int CP_NOCLOSE_BUTTON = 0x200;
protected override CreateParams CreateParams 
{
   get 
   {
      CreateParams cp = base.CreateParams;
      cp.ClassStyle = cp.ClassStyle | CP_NOCLOSE_BUTTON;
      return cp;
   }
}

在应用程序启动时运行静态Main方法的主程序中,我将默认Application.Run更改为:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        SystemTrayApp systemTrayApp = new SystemTrayApp();
        systemTrayApp.Text = "File Copy Service Controller";

        // Show the instance of the form modally.
        systemTrayApp.ShowInTaskbar = true;
        systemTrayApp.ShowDialog();
        Application.Run();
    }
 }

现在显示Windows窗体的设计页面,右键单击窗体并选择属性,然后选择事件按钮以显示窗体的所有事件。向下滚动到Shown事件并双击,将在源代码中添加一个新的事件处理程序。导航到该方法并将this.Hide()添加到处理程序:

// Runs the first time the application starts
private void SystemTrayApp_Shown(object sender, EventArgs e)
{
   this.Hide();
}

最后打开Windows窗体项目的属性页面,然后选择“应用程序”选项卡。在“启动对象”下,选择“程序”类作为启动对象。

您需要在对话框中添加一个按钮或菜单控件,以便在不终止应用程序的情况下关闭表单,设置按钮或菜单控件以隐藏应用程序,使其在系统托盘中运行。

答案 1 :(得分:1)

  • 您是否尝试捕捉VisibleChanged事件?

this.Shown += new EventHandler(Form1_Shown);

void Form1_Shown(object sender, EventArgs e)
{
    this.Hide();
}
  • 您还可以尝试通过覆盖WndProc来拦截邮件。
    protected override void WndProc(ref Message m)
    {
        const int SW_SHOW = 5;
        if (m.Msg == SW_SHOW)
        {
            //DoSomething();
        }

        base.WndProc(ref m);
    }
  • 典型的消息泵如下所示:
MSG msg;
while(GetMessage(&msg, hwnd, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    // DoSomething.
}

答案 2 :(得分:1)

替换Application类中的消息循环是不切实际的。那么样板Windows消息循环还有很多。无论如何,这不是真正的问题,Application类通过调用ShowWindow()强制表单变得可见。这是必要的,因为表单是懒惰地初始化的,没有ShowWindow()调用它从不创建本机Window句柄。

通过重写SetVisibleCore(),可以在常规.NET框架版本中轻松修复此问题:

protected override void SetVisibleCore(bool value) {
  if (!this.IsHandleCreated) {
    this.CreateHandle();
    value = false;  // Prevent becoming visible the first time
  }
  base.SetVisibleCore(value);
}

但我认为这不适用于CF.要找到解决方案,您需要准确解释为什么要阻止UI显示。没有任何创建的窗口句柄,应用程序通常死为doornail。它可以像延迟Application.Run()调用一样简单。