蛋疼的讓C#控制台程序(Console)像窗體(Winform)一樣(關閉,托盤圖標,事件響應,手動退出等)
前言:
你可以把這篇文章定義為一篇蛋疼的文章,應為這個東西不怎么實用,還費神,沒事折騰這做什么。恩,的確,蛋疼。我也同意,就算蛋疼也有它的小眾范圍,當你不想做webservers,winform等,就想蛋疼的拿控制台來做服務,做程序,行嗎?行,但是控制台一點關閉就退出了,有時會點錯,控制台沒有托盤圖標,想最小化到托盤圖標等,還有什么蛋疼的想法,來吧,讓我們來實現他們。
需要了解:
需要了解:
console application是控制台程序。
控制台不是winform,我們不能設置它的關閉事件等。
控制台雖然可以通過添加引用來增加托盤圖標,但是托盤圖標沒有事件。
哇,怎么都是不能,那不是不能實現。
所以你還需要了解:
我們可以通過引用外部dll的api來捕獲到關閉事件等。
我們可以給控制台添加消息事件循環來捕獲事件響應讓托盤圖標可以觸發事件。
那么我們的思路是:
那么我們的思路是:
禁用關閉按鈕,讓用戶在控制台輸入exit進行退出,當控制台被其他事件關閉時可以進行處理。
用Application.DoEvents()來捕獲消息事件處理,但是要用死循環來控制,那么我們怎么監聽輸入呢?
我們在開一個線程用來監聽輸入。
蛋疼的可以,搞個這還這么麻煩!
別慌,還需要你解決的問題:
別慌,還需要你解決的問題:
先了解我給出的代碼實現了什么。實現了禁用關閉按鈕,托盤圖標的添加和事件的處理。
你要做的是什么,當然你可以不做,如果你也想蛋疼一下,就來解決下這個問題吧。
退出控制台時,托盤圖標沒有消失,唉,這是bug,怎么解決?
捕獲關閉事件,在要關閉時清除托盤圖標。
先告訴你可以實現,我以實驗成功,這里沒有放出來是讓你也蛋疼下。
好了,代碼如下:
好了,代碼如下:
/*
* 控制台禁用關閉按鈕並最小化到系統托盤演示
*
* 通過ConsoleWin32類來進行控制
* 添加引用 System.Runtime.InteropServices; 和 System.Threading; 用於禁用關閉按鈕
* 添加引用 System.Drawing; 和 System.Windows.Forms; 用於系統托盤
*
*/
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Runtime.InteropServices;
using
System.Threading;
using
System.Drawing;
using
System.Windows.Forms;
namespace
Tray_beta_1
{
class
Program
{
static
bool
_IsExit
=
false
;
static
void
Main(
string
[] args)
{
Console.Title
=
"
TestConsoleLikeWin32
"
;
ConsoleWin32Helper.ShowNotifyIcon();
ConsoleWin32Helper.DisableCloseButton(Console.Title);
Thread threadMonitorInput
=
new
Thread(
new
ThreadStart(MonitorInput));
threadMonitorInput.Start();
while
(
true
)
{
Application.DoEvents();
if
(_IsExit)
{
break
;
}
}
}
static
void
MonitorInput()
{
while
(
true
)
{
string
input
=
Console.ReadLine();
if
(input
==
"
exit
"
)
{
_IsExit
=
true
;
Thread.CurrentThread.Abort();
}
}
}
}
class
ConsoleWin32Helper
{
static
ConsoleWin32Helper()
{
_NotifyIcon.Icon
=
new
Icon(
@"
G:\BruceLi Test\ConsoleAppTest\ConsoleApps\Tray\small.ico
"
);
_NotifyIcon.Visible
=
false
;
_NotifyIcon.Text
=
"
tray
"
;
ContextMenu menu
=
new
ContextMenu();
MenuItem item
=
new
MenuItem();
item.Text
=
"
右鍵菜單,還沒有添加事件
"
;
item.Index
=
0
;
menu.MenuItems.Add(item);
_NotifyIcon.ContextMenu
=
menu;
_NotifyIcon.MouseDoubleClick
+=
new
MouseEventHandler(_NotifyIcon_MouseDoubleClick);
}
static
void
_NotifyIcon_MouseDoubleClick(
object
sender, MouseEventArgs e)
{
Console.WriteLine(
"
托盤被雙擊.
"
);
}
#region
禁用關閉按鈕
[DllImport(
"
User32.dll
"
, EntryPoint
=
"
FindWindow
"
)]
static
extern
IntPtr FindWindow(
string
lpClassName,
string
lpWindowName);
[DllImport(
"
user32.dll
"
, EntryPoint
=
"
GetSystemMenu
"
)]
static
extern
IntPtr GetSystemMenu(IntPtr hWnd, IntPtr bRevert);
[DllImport(
"
user32.dll
"
, EntryPoint
=
"
RemoveMenu
"
)]
static
extern
IntPtr RemoveMenu(IntPtr hMenu,
uint
uPosition,
uint
uFlags);
///
<summary>
///
禁用關閉按鈕
///
</summary>
///
<param name="consoleName">
控制台名字
</param>
public
static
void
DisableCloseButton(
string
title)
{
//
線程睡眠,確保closebtn中能夠正常FindWindow,否則有時會Find失敗。。
Thread.Sleep(
100
);
IntPtr windowHandle
=
FindWindow(
null
, title);
IntPtr closeMenu
=
GetSystemMenu(windowHandle, IntPtr.Zero);
uint
SC_CLOSE
=
0xF060
;
RemoveMenu(closeMenu, SC_CLOSE,
0x0
);
}
public
static
bool
IsExistsConsole(
string
title)
{
IntPtr windowHandle
=
FindWindow(
null
, title);
if
(windowHandle.Equals(IntPtr.Zero))
return
false
;
return
true
;
}
#endregion
#region
托盤圖標
static
NotifyIcon _NotifyIcon
=
new
NotifyIcon();
public
static
void
ShowNotifyIcon()
{
_NotifyIcon.Visible
=
true
;
_NotifyIcon.ShowBalloonTip(
3000
,
""
,
"
我是托盤圖標,用右鍵點擊我試試,還可以雙擊看看。
"
, ToolTipIcon.None);
}
public
static
void
HideNotifyIcon()
{
_NotifyIcon.Visible
=
false
;
}
#endregion
}
}
