Since Compact Framework calls Show()
on the form passed to Application.Run()
,我决定创建自己的消息泵。
我不知道我该怎么做。
任何帮助(如一个简单的例子)将不胜感激。
答案 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. }
Application.DoEvents()
方法。答案 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()调用一样简单。