为了创建一个主窗口不显示的应用程序,我做了若干个探索。结果绕了几个弯,回到最简朴的没有窗体的世界中。

由此发现,我已经对窗体设计器产生了严重的依赖性,而且自已已经懒得不得了了--哪怕只有几行的代码,也要IDE自动生成。

我将探索过程,以及最后的解决,全部呈现出来,希望能对大家有点帮助。

2006-03-16 原文

2006-03-17    修订  2006-03-30    修订

2006-03-16 多云

一般在使用NotifyIcon时,都会有一个主窗口。当最小化或关闭主窗口后,可以从NotifyIcon再次显示主窗口。

这两天在写一个小程序时,想要一个没有窗口的桌面应用,它在工作时不需要窗口显示,顶多用BalloonTip显示一些提示信息。但是在实践中发现,NotifyIcon必须放在窗口中,窗口必须被创建才能显示NotifyIcon。

最初想的办法是在窗口建立时调用Hide或Visible=false,均不起作用;如果在Shown事件中Hide,则窗口会一闪而过,达不到要求。

看了一下Main函数:

Application.Run(newFormMain());

于是认为可能主窗口一定要显示出来的。既然这样,就干脆不要主窗口了,改写Main函数为:

using(newFormMain())

    Application.Run();

能满足效果。但是发现,再也不能用Close来关闭应用程序,因为此时没有主窗口了,只能使用Application.Exit来关闭应用程序。而关闭应用程序时,不会去结束FormMain,因为FormMain没有显示,不属于Application管理,因此就要使用using来让应用程序结束前自动析构FormMain。

-------------------------------------------------

BTW:

另外,需要一些设置参数的对话框。于是定义在NotifyIcon的右键菜单中。运行时发现,可以无数次的点选菜单显示对话框,导致对话框在屏幕上同时显示多个出来;试了几种方法后,决定采用遍历Application.OpenForms的方法来确认是否已有对话框显示:

publicstaticDialogResult DoDialog(Form owner) where T : Form,new()

{

foreach(Form finApplication.OpenForms)

{

if(f.Modal)

{

            f.BringToFront();

returnDialogResult.None;

        }    }

using(T dlg=newT())

returndlg.ShowDialog(owner);

}

这样在菜单中只要调用DoDialog就可以保证只有一个对话框在显示了:

privatevoidaboutToolStripMenuItem_Click(objectsender, EventArgs e)

{

    DoDialog(this);

}

2006-03-17 多云转晴

随后用reflector来反编译Application.Run方法,试图找出其设置主窗口一定要显示的原因:

publicstaticvoidRun(Form mainForm)

{

  Application.ThreadContext.FromCurrent().RunMessageLoop(-1,newApplicationContext(mainForm));

}

RunMessageLoop则直接调用了RunMessageLoopInner,其参数reason为-1,意为主窗口。RunMessageLoopInner的部份代码如下:

if(reason==-1)

{

if(this.applicationContext.MainForm!=null)

{

this.applicationContext.MainForm.Visible=true;

  }

}

也就是说,创建窗口时,无论如何让窗口隐藏,当到了最后一刻,还是要被显示出来。你只能在显示后再做努力。但无论如何努力,都不能改变窗口被显示的事实,结果只能是一闪而过。

而visible属性的实现,是通过SetVisibleCore(bool value)来实现的。这样倒有了一个简便的方法了,重写 SetVisibleCore 就可以了:

protectedoverridevoidSetVisibleCore(boolvalue){}//或protectedoverridevoidSetVisibleCore(boolvalue)

{

base.SetVisibleCore(false);

}

但是这种方法仍然不能用Close主窗口的方式来关闭应用程序,还得使用Application.Exit。

搞到这里,突然发现自已昏了头了,不就是不让窗口显示出来嘛,只要能骗过人就可以了,最简单莫过于设置 ShowInTaskBar 为 false、WindowState 为 Minimized。这样还可以用Close主窗口的方式来关闭应用程序。

最后做一个小结:

1. 最简单的方法就是让主窗口最小化并且不显示在任务栏上:设置 ShowInTaskBar 为 false、WindowState 为 Minimized。此时,由于主窗口会被创建,因此,可以在主窗口安放所有类型的控件,并且可以使用Close主窗口的方式来关闭应用程序。

2. 可以采用重写SetVisibleCore方法,禁止窗口显示。同时该窗口并不会被创建。因此,需要主窗口作容器的控件可能不能正常工作,而且,不能使用Close主窗口的方式来关闭应用程序--主窗口根本就没创建出来啊。

3. 修改Main函数,不为Application.Run指定主窗口。这时,可以Run之前摆弄自已的窗口。但不管窗口是否创建,只要不是主窗口,就只能采用Application.Exit的方式退出应用程序。

好了,我已经发现自已实在是笨到家了。既然不用创建窗口都可以使用NotifyIcon和ContextMenu/ContextMenuStrip,那我何必非要把它们摆上Form呢?直接在Main中创建NotifyIcon和ContextMenu不就完事了吗?这才叫没有窗口的程序啊。

staticvoidMain()

{

            Application.EnableVisualStyles();

            Application.SetCompatibleTextRenderingDefault(false);

            System.Resources.ResourceManager resources = new System.Resources.ResourceManager("myResource", System.Reflection.Assembly.GetExecutingAssembly());            NotifyIcon ni=newNotifyIcon();

            ni.BalloonTipIcon=System.Windows.Forms.ToolTipIcon.Warning;

            ni.BalloonTipText="Hello world!";

            ni.BalloonTipTitle="Hi.";

//ni.ContextMenuStrip = contextMenu;ni.Icon=((System.Drawing.Icon)(resources.GetObject("ni.Icon")));

            ni.Text="Hello world!";

            ni.Visible=true;

            ni.MouseClick+=delegate(objectsender, MouseEventArgs e)

{

                ni.ShowBalloonTip(0);

            };

            Application.Run();

        }

2006-03-30 晴

1.萧寒网友的方法

和SetVisibleCore一样简单,重写CreateParams属性方法可以实现:

protectedoverrideCreateParams CreateParams{

get{

                Hide();

returnbase.CreateParams;

            }        }

这个方法能够创建窗口,并且能够使用Close来关闭主窗口和应用程序。因此,算得上是最方便的方法了。Hide在这里比较关键。我试过,去掉CreateParams的WS_VISIBLE标志位是不能够隐藏窗口的。

2.Santé网友的《WinForm程序启动时不显示主窗体的实现方法》

这种方法也是改变Application.Run的主窗口。继承ApplicationContext来管理主窗口的生命周期,可以给人不少的启发:

internalclassHideOnStartupApplicationContext : ApplicationContext{

publicHideOnStartupApplicationContext(Form mainForm){

            mainForm.Closed+=delegate(objectsender, EventArgs e){

                Application.Exit();

            };

        }    }

staticvoidMain()

{

        Application.Run(newHideOnStartupApplicationContext(newMainForm()));

    }

不过要注意的是,这种方法也是采用不创建主窗口的方法。因此,如果需要创建主窗口,目前好象只有两种方法可以做到:

a. 将窗口最小化,并且不显示在任务栏上。

b. 使用萧寒的方法,重写CreateParams。

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=661725

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2138643

c#窗体程序生成错误_创建一个没有窗口的程序 (C#) | 学步园相关推荐

  1. 闪亮蔚蓝_创建一个闪亮的应用程序以使用rtweet和R搜索Twitter

    闪亮蔚蓝 您是否要在Twitter上跟踪会议的主题标签(或任何主题标签)? 该奖金"用R实现更多功能"教程逐步向您展示如何创建交互式Shiny Web应用程序,以使用特定的主题标签 ...

  2. c#窗体程序生成错误_用C#语言做的窗体程序中出错恶劣怎么办?

    我使用的SQLserver2005中,建有数据库stuDB,内有表stuInfo, 此表中有一字段stuSex,数据内型是NCHAR(4),没其他约束,当然,性别只有"男"和&qu ...

  3. 创建一个Windows Service应用程序

    创建一个Windows Service应用程序 下载本文代码 见资源 正是由于.NET Framework的出现,才使你能够构建出在系统重新启动时自动运行的.无人参与的(unattended)应用程序 ...

  4. 使用timer控件创建一个简单的报警程序

    简介: 当我使用计算机工作时,我总是如此的专心致志,以至于每当我过了"一会儿"去看时间时,发现已经过了三个小时,而我却完全没有意识到!所以我决定使用我从Code Project学来 ...

  5. ruby on rails_最终的中级Ruby on Rails教程:让我们创建一个完整的应用程序!

    ruby on rails 由Domantas G (By Domantas G) There are plenty tutorials online which show how to create ...

  6. python生成一个窗口_PyQt5创建一个新窗口的实例

    更多python教程请到友情连接: 菜鸟教程www.piaodoo.com 人人影视www.sfkyty.com 飞卢小说网www.591319.com 韩剧网www.op-kg.com 兴化论坛ww ...

  7. Qt Creator创建一个Qt Quick应用程序

    Qt Creator创建一个Qt快速应用程序 创建一个Qt快速应用程序 创建项目 创建主视图 连接鼠标单击以陈述更改 动画过渡 创建一个Qt快速应用程序 本教程使用内置的QML类型,并说明了Qt Qu ...

  8. OpenGL创建一个GLFW窗口的实例

    OpenGL创建一个GLFW窗口 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #include < ...

  9. Java黑皮书课后题第8章:8.9(井字游戏)玩家使用各自标志标记3*3网格中的某个空格,当一个玩家在网格的水平、垂直或对角线方向标记了三个相同的标记时,游戏结束,该玩家获胜。创建一个玩井字游戏的程序

    ***8.9(井字游戏)玩家使用各自标志标记3*3网格中的某个空格,当一个玩家在网格的水平.垂直或对角线方向标记了三个相同的标记时,游戏结束,该玩家获胜.创建一个玩井字游戏的程序 题目 题目描述与运行 ...

最新文章

  1. 关于 Rocksdb 的 EnvWrapper 作用的小讨论
  2. Spring基础专题——第六章(Aop编程)
  3. 报名丨图神经网络前沿学术研讨会:清北高校vs企业,9位学者联袂分享
  4. 一个 .Net Hashtable 的锁的疑惑和解决
  5. 如何在圆柱表面滚花纹_更多地了解圆柱形铣刀
  6. .Net 1.1下WEB引用Win控件的两个Bug
  7. 从第一范式(2nf)到第二范式(3nf)_啥是数据库范式
  8. 电脑磁盘空间不足怎么办_Mac磁盘总是提示空间不足?学会这几招,瞬间腾出几个G...
  9. eclipse 集成svn客户端_TortoiseSVN及Eclipse的svn插件安装使用
  10. coreseek使用
  11. ArcGis拓扑——规则、概念与要点
  12. iOS开发-class_ro_t和class_rw_t的区别
  13. 深度探索c++对象模型(5):ctor、dtor、copy
  14. Lm317电压源芯片制作电流源
  15. html页面实现打印预览功能,js实现打印、页面设置、打印预览功能
  16. 安装blockchain-explorer区块浏览器
  17. 微信小程序接入微信支付全流程(koa2)
  18. 在ubuntu20.04环境下安装opencv教程并测试
  19. python pandas 豆瓣电影 top250 数据分析
  20. 移动机器人传感器外参标定综述

热门文章

  1. html 预选单选按钮,关于html:单选按钮的预选
  2. 选课系统 - 数据库查询(一)
  3. 如何将pdf转换成ppt?
  4. 禅道 upgrade.php,zentao禅道安装升级
  5. GeeM2引擎弹出装备显示框的设置方法
  6. ansible之判断语句jinja2模板的使用 与roles角色的配置使用
  7. es - elasticsearch - search - DSL - specialized - pinned
  8. amCharts 5.1.12 Crack
  9. 注册微信小程序的操作步骤
  10. 三菱FX系列PLC数据采集和点表自动侦测