Пользовательский фильтр сообщений для приложения SmartDevice - PullRequest
1 голос
/ 30 марта 2010

Поскольку Compact Framework вызывает Show() в форме, переданной Application.Run(), я решил создать свой собственный обработчик сообщений.

Понятия не имею, как мне это сделать.

Любая помощь (например, простой пример) будет оценена.

Ответы [ 3 ]

2 голосов
/ 02 января 2011

Я обнаружил, что это большая проблема, чем вы ожидаете от приложения Windows Form. Для своего решения я вытащил предложения с трех разных сайтов и нашел, что это решение работает очень хорошо. Для моих нужд у меня есть служба Windows, которая имеет компонент контроллера пользовательского интерфейса в системном трее. Пользовательский интерфейс должен быть свернут с помощью иконки в трее и контекстного меню для иконки. При активации пользовательский интерфейс работает как модальное диалоговое окно, позволяя пользователю запустить длительный процесс в фоновом потоке, после запуска пользовательский интерфейс должен возобновить получение ответов от пользователя.

В конструкторе для класса 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, чтобы пользователь мог перемещать диалог по экрану, но не изменять его размер, чтобы отключить кнопку закрытия формы, красный крестик в правом верхнем углу формы, который я использовал:

// 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 Form и выберите вкладку «Приложение». Под объектом Автозагрузка выберите класс Программы в качестве объекта запуска.

Вам потребуется добавить кнопку или элемент управления меню в диалоговое окно, чтобы разрешить закрытие формы без завершения приложения, установить кнопку или элемент управления меню, чтобы скрыть приложение, оставив его работающим в системном трее.

1 голос
/ 30 марта 2010

Замена цикла сообщений в классе Application нецелесообразна. Существует гораздо больше, чем шаблонный цикл сообщений Windows. В любом случае, это не настоящая проблема, класс Application заставляет форму стать видимой при вызове ShowWindow (). Это необходимо, потому что формы лениво инициализируются, без вызова ShowWindow () он никогда не создает собственный дескриптор Window.

Эту проблему легко исправить в обычной версии .NET Framework, переопределив SetVisibleCore ():

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

Но я не думаю, что это доступно в CF. Чтобы найти решение, вам нужно точно объяснить , почему вы хотите запретить отображение пользовательского интерфейса. Без какого-либо созданного дескриптора окна приложение обычно мертво, как рупор. Это может быть так же просто, как отложить вызов Application.Run ().

1 голос
/ 30 марта 2010
  • Вы пытались поймать событие 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.
}
...