C#控制台程序(Console)像窗體(Winform)一樣(關閉,托盤圖標,事件響應,手動退出等)轉


蛋疼的讓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
}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM