C# 程式小片段

整理一些偶爾會用到的小片段。因為是小片段,多半是簡單跑的,有些不能直接跑,需要自己修改應用

最近在整理一些以前寫的程式,看有哪些部分可以整理出來做成文章

到時候再補充

使用 Thread運行 畫在螢幕上的文字訊息

使用 NotifyIcon 達到最小化到系統列

利用 System.Threading.Mutex 做程式唯一開啟,不能重複開啟程式

利用 Stopwatch 計算經過時間,當作測試效能依據

WindowsForm的DataGridView自畫格線

利用Linq將字串 比對 Array裡的關鍵字移除


static string drawString = "";
static System.Drawing.Font drawFont = new System.Drawing.Font("Arial", 12);
static System.Drawing.SolidBrush drawBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
static System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat();
static void MyTask()
{
    for (;;)
    {
        using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
        {
            // 塗上背景色,不然文字會重疊
            g.FillRectangle(Brushes.WhiteSmoke, 30, 28, 120, 34);
            // 畫上文字
            g.DrawString(drawString, drawFont, drawBrush, 30, 30, drawFormat);
        }
        Thread.Sleep(100);
    }
}
Thread thread1 = new Thread(MyBackgroundTask);
thread1.IsBackground = true;
thread1.Start();
//宣告NotifyIcon
private System.Windows.Forms.NotifyIcon notifyIcon1;

設定 NotifyIcon 相關資訊,使用MouseDoubleClick 是為了讓他最小化可以還原

//指定使用的容器
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
//建立NotifyIcon
this.notifyIcon1.Icon = new Icon("myIcon.ico");
this.notifyIcon1.Text = "AppName";
this.notifyIcon1.MouseDoubleClick += new MouseEventHandler(this.notifyIcon1_MouseDoubleClick);
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
    this.Show();
    this.WindowState = FormWindowState.Normal;
}

另外要一進入就最小化的功能的話

請自行添加 Form1_Shown 事件,在裡面補充。寫在 Form1_Load 沒用,因為這時候視窗還沒開啟

private void Form1_Shown(object sender, EventArgs e)
{
    if (bFirst) // 記錄是否為軟體第一次開啟
    {
        bFirst = false;
        this.Hide();
        this.notifyIcon1.Visible = true;
        this.notifyIcon1.ShowBalloonTip(5000, "開啟成功""開啟成功"ToolTipIcon.Info);
    }
}
// 是否可以開新的
bool canCreateNew;
// 獲取程式的Guid 作為唯一標識
Attribute guid_attr = Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(GuidAttribute));
string guid = ((GuidAttribute)guid_attr).Value;
// 利用 Mutex 判斷是否已經有開啟
var _mutex = new System.Threading.Mutex(true, guid, out canCreateNew);
if (false == canCreateNew)
{
    // 發現重複
    MessageBox.Show("重複開啟""重複開啟"MessageBoxButtons.OK, MessageBoxIcon.Error);
    return;
}
_mutex.ReleaseMutex();
Stopwatch sw = new Stopwatch();
sw.Reset();
sw.Start();
for (int i = 0; i < 10; ++i)
{
    // Test Region
}
sw.Stop();
// Console專案用
Console.WriteLine($"{sw.ElapsedMilliseconds}");
// IDE輸出用
Debug.WriteLine($"{sw.ElapsedMilliseconds}");

因為需要用到DataGridViewCellPaintingEventArgs參數,所以需要掛在CellPainting事件內

效果是簡單畫個格線,給個基礎版本,有需要的可利用這方法去擴充,使用上有一些小問題

如cell選取之後造成格線消失之類的。一些實務上的問題有需要用的人在自行研究吧

public static void GridLinePrint(DataGridViewCellPaintingEventArgs eventArgs,
                                  string[] line, int thickness, Color color)
{
    Rectangle rectBounds = eventArgs.CellBounds;
 
    using (Brush gridBrush = new SolidBrush(color))
    {
        using (Pen gridLinePen = new Pen(gridBrush, thickness))
        {
            if (line.Contains("B") || line.Contains("Bottom"))
            {   // 下 bottom
                Point blPoint = new Point(rectBounds.Left, rectBounds.Bottom);
                Point brPoint = new Point(rectBounds.Right, rectBounds.Bottom);
                eventArgs.Graphics.DrawLine(gridLinePen, blPoint, brPoint);
            }
            if (line.Contains("T") || line.Contains("Top"))
            {   // 上 Top
                Point tlPoint = new Point(rectBounds.Left, rectBounds.Top);
                Point trPoint = new Point(rectBounds.Right, rectBounds.Top);
                eventArgs.Graphics.DrawLine(gridLinePen, tlPoint, trPoint);
            }
 
            if (line.Contains("L") || line.Contains("Left"))
            {   // 左 Left
                Point ltPoint = new Point(rectBounds.Left, rectBounds.Top);
                Point lbPoint = new Point(rectBounds.Left, rectBounds.Bottom);
                eventArgs.Graphics.DrawLine(gridLinePen, ltPoint, lbPoint);
            }
            if (line.Contains("R") || line.Contains("Right"))
            {   // 右 Right
                Point rtPoint = new Point(rectBounds.Right, rectBounds.Top);
                Point rbPoint = new Point(rectBounds.Right, rectBounds.Bottom);
                eventArgs.Graphics.DrawLine(gridLinePen, rtPoint, rbPoint);
            }
        }
    }
}

當有一個存載關鍵字的 Array,而有一個字串

需要跟Array比對,只要有一樣的即移除

(此做法有許多變形,只需要多發揮想像力就可以達到不同效果)

原本是需要用迴圈去把Array的資料全跑一次,只是改用Linq去取代迴圈

外觀看起來比較直覺(?)

var tempString = "需要比對的文字資料";
 
// RemoveKeyWord 是存載 所有關鍵字的 array
RemoveKeyWord.All(s =>
{   // 利用linq移除關鍵字
    if (tempString.Contains(s))
    {
        tempString = tempString.Replace(s, "");
    }
    return true;//  因為是All,如果Return false就會立即停止了
});