顯示具有 C# 標籤的文章。 顯示所有文章
顯示具有 C# 標籤的文章。 顯示所有文章

2014年6月25日 星期三

[C#/winform] MSChart使用實測+功能介紹

關於這個Microsoft Chart Control,網路上真的資料不多(不然就是簡體居多),有鑒於此,

這邊研究了很久以後...終於了解了一個大概,這邊寫一下心得跟使用說明。
























可以看到Series就代表一條線(或是一組線,或數據),你可以透過Series調整他的各項功能

ChartArea: 這線所畫的區域

ChartType: 要怎樣的圖形表示呢? 折線/直條/橫條...等

像我這這邊加入了4個Series,因為我要做四條線(但下面範例我只有設定2條而已)



這邊可以看到Legends代表上面那個線條註釋,而底下如果太多數據要顯示(內建會變成一個顯示一個不顯示)就要用程式碼修改為不重疊(交叉顯示)。

以下範例是參考 SUEHILARY的學習手記 修改而成的:

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

            DateTime a = DateTime.Now;
            DateTime b = DateTime.Now;

            List<String> xValue = new List<string>();

            xValue.Add(a.ToString());
            xValue.Add(b.ToString());

            string[] titleArr = { "活動1", "活動2" };
            double[] yValues = { 269.23, 94 };
            double[] yValues2 = { 120.14, 116 };

            Chart1.Legends.Add("Legends1"); //圖例集合

            //設定 Chart
            Title title = new Title();
            title.Text = "統計圖";
            title.Alignment = ContentAlignment.MiddleCenter;
            title.Font = new System.Drawing.Font("Trebuchet MS", 14F, FontStyle.Bold);
            Chart1.Titles.Add(title);

            //設定 ChartArea----------------------------------------------------------------------
         
            //-----------------------------設定3D------------------------------//
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = true; //3D效果
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.IsClustered = true; //並排顯示
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.Rotation = 40; //垂直角度
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.Inclination = 50; //水平角度
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.PointDepth = 10; //數據條厚度
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.WallWidth = 0; //外牆寬度
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.LightStyle = LightStyle.Realistic; //光源
            //-----------------------------設定3D------------------------------//

            Chart1.ChartAreas["ChartArea1"].BackColor = Color.FromArgb(240, 240, 240); //背景色
            Chart1.ChartAreas["ChartArea1"].AxisX.Enabled = AxisEnabled.True;
            Chart1.ChartAreas["ChartArea1"].AxisX2.Enabled = AxisEnabled.False; //隱藏 X2 標示
            Chart1.ChartAreas["ChartArea1"].AxisY2.Enabled = AxisEnabled.False; //隱藏 Y2 標示
            Chart1.ChartAreas["ChartArea1"].AxisY2.MajorGrid.Enabled = false;   //隱藏 Y2 軸線
            Chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.LineColor = Color.FromArgb(150, 150, 150);//X 軸線顏色
            Chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.LineColor = Color.FromArgb(150, 150, 150);//Y 軸線顏色


            Chart1.ChartAreas["ChartArea1"].AxisY.LabelStyle.Format = "#.###";//設定小數點

            //設定 Legends------------------------------------------------------------------------              
            Chart1.Legends["Legends1"].DockedToChartArea = "ChartArea1"; //顯示在圖表內
            //Chart1.Legends["Legends1"].Docking = Docking.Bottom; //自訂顯示位置
            Chart1.Legends["Legends1"].BackColor = Color.FromArgb(235, 235, 235); //背景色
            //斜線背景
            Chart1.Legends["Legends1"].BackHatchStyle = ChartHatchStyle.DarkDownwardDiagonal;
            Chart1.Legends["Legends1"].BorderWidth = 1;
            Chart1.Legends["Legends1"].BorderColor = Color.FromArgb(200, 200, 200);

            //設定 Series-----------------------------------------------------------------------
            //Chart1.Series["Series1"].ChartType = SeriesChartType.Line; //直條圖(Column),折線圖(Line),橫條圖(Bar)
            //Chart1.Series["Series2"].ChartType = SeriesChartType.Line; //直條圖(Column),折線圖(Line),橫條圖(Bar)
            //Chart1.Series["Series1"].ChartType = SeriesChartType.Bar; //橫條圖

            Chart1.Series["Series1"].Points.DataBindXY(xValue, yValues);//Series1的XY數值放入圖中

            Chart1.Series["Series1"].Legend = "Legends1";
            Chart1.Series["Series1"].LegendText = titleArr[0];
            Chart1.Series["Series1"].LabelFormat = "#.###"; //小數點
            Chart1.Series["Series1"].MarkerSize = 8; //Label 範圍大小
            Chart1.Series["Series1"].LabelForeColor = Color.FromArgb(0, 90, 255); //字體顏色
            //字體設定
            Chart1.Series["Series1"].Font = new System.Drawing.Font("Trebuchet MS", 10, System.Drawing.FontStyle.Bold);
            //Label 背景色
            Chart1.Series["Series1"].LabelBackColor = Color.FromArgb(150, 255, 255, 255);
            Chart1.Series["Series1"].Color = Color.FromArgb(240, 65, 140, 240); //背景色
            Chart1.Series["Series1"].IsValueShownAsLabel = true; // Show data points labels

            Chart1.Series["Series2"].Points.DataBindXY(xValue, yValues2);

            Chart1.Series["Series2"].Legend = "Legends1";
            Chart1.Series["Series2"].LegendText = titleArr[1];
            Chart1.Series["Series2"].LabelFormat = "#.###"; //小數點
            Chart1.Series["Series2"].MarkerSize = 8; //Label 範圍大小
            Chart1.Series["Series2"].LabelForeColor = Color.FromArgb(255, 103, 0);
            Chart1.Series["Series2"].Font = new System.Drawing.Font("Trebuchet MS", 10, FontStyle.Bold);
            Chart1.Series["Series2"].LabelBackColor = Color.FromArgb(150, 255, 255, 255);
            Chart1.Series["Series2"].Color = Color.FromArgb(240, 252, 180, 65); //背景色
            Chart1.Series["Series2"].IsValueShownAsLabel = true; //顯示數據

            Chart1.Series["Series3"].Color = Color.FromArgb(22, 24, 18, 65); //背景色

            Chart1.ChartAreas[0].AxisX.Interval = 1;   //設置X軸坐標的間隔為1
            Chart1.ChartAreas[0].AxisX.IntervalOffset = 1;  //設置X軸坐標偏移為1
            Chart1.ChartAreas[0].AxisX.LabelStyle.IsStaggered = true;   //設置是否交錯顯示,比如數據多的時間分成兩行來顯示

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

原本應該是要先宣告

Chart Chart1 = new Chart();

但我們已經拉了一個元件叫Chart1因此就不用再new(再new就會重複,造成錯誤)

而Series1,2也是因為在winform當中有設定過因此無須重複設定(一樣造成錯誤)

3D的部分,因人而異,但個人是建議

            Chart1.ChartAreas["ChartArea1"].Area3DStyle.IsClustered = true; //並排顯示
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.Rotation = 40; //垂直角度
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.Inclination = 50; //水平角度
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.PointDepth = 10; //數據條厚度
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.WallWidth = 0; //外牆寬度
            Chart1.ChartAreas["ChartArea1"].Area3DStyle.LightStyle = LightStyle.Realistic; //光源

這樣的設定比較好看,當然也可以改為不要並排顯示,一切取決於你的程式/數據多寡

背景色的部分應該無須多講解吧?

線條顏色修改的部分在Chart1.Series["Series"].Color = Color.FromArgb(自行設定色彩);

然後要修改Legend的文字則是在Chart1.Series["Series"].LegendText = "要顯示的文字";

目前遇到的問題跟解法都寫在這邊了,剩下的部分就等寫完再補一篇新的。

End

[C#] DateTime格式及如何運用

常常會用到DateTime,但每次都要上網查,所以寫下來以免忘記


1. DateTime.Now //記錄現在時間

這邊如果要顯示在winform一定要轉換成string,所以我們用.ToString()來轉換。

轉換出來結果一定是一長串"年/月/日 上/下午 小時:分鐘:秒"


2.進階轉換

DateTime.ToString("yyyymmdd") //20140625

DateTime.ToString("yyyy-mm-dd") //2014-06-25

DateTime.ToString("yyyy/m/d") //2014/6/25

DateTime.ToString("hh:mm:ss") // 11:12:13

DateTime.ToString("hh:mm")  //11:12

DateTime.ToString("T") //上午11:12:13

DateTime.ToString("t") //上午11:12:

DateTime.ToString("tt") //上午

3.只取某部分時間

DateTime.Minute.ToString(); //只取分鐘

DateTime.Second.ToString()//只取秒

....

4.計算時間差

TimeSpan  TS1 = new TimeSpan(DateTime.Tick); //DateTime部分請自行轉換成要計算的第一個數值
TimeSpan  TS2 = new TimeSpan(DateTime.Tick); //DateTime部分請自行轉換成要計算的第二個數值
TimeSpan Sub = TS1.subtract(TS2).Duration();

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


DateTime用法不外乎上面幾項,用熟了即可

End

2014年6月13日 星期五

[C#/winform] ComboBox + List

稍為紀錄一下,以免每次都忘記。

首先還是先用list把要用的資料add()進去,這點應該滿容易的。

只要記得加入的時候可以用條件是list<>.contain(內容)檢查是否已經存在list內了

然後如果要讓combobox能夠條列顯示list所有內容,就用ComboBox.DataSourse = List<> ;

這樣就可以把list所有內容都加入ComboBox選項內囉!

十分容易,end。

2014年5月9日 星期五

[C#] txt or csv檔案 多次重新讀取

通常我們讀檔都會使用StreamReader,但往往只能讀一次,無法從頭開始。

最基本的如下:

try
{
     using (StreamReader SR = new StreamReader(路徑)
    {
          string Line;

           while ((Line = SR.ReadLine()) != null) //一次讀一行
           {
                  string[] ReadLine_Array = Line.Split(',');//csv檔用逗號做分隔
                  //這邊可以處理文件
           }
     }
 }
 catch (IOException)
 { }
 catch (NullReferenceException)
 { }
 catch (FormatException)
 { }

在using裡面讀完一次就無法再從頭讀起,因此我們需要增加

StreamReader.ReadToEnd();//標頭拉到尾
StreamReader.BaseStream.Seek(0, SeekOrigin.Begin);//標頭重新回到最開始

增加以後就可以讓 檔案再次從頭讀起!

End

2014年4月22日 星期二

[C#] 如何打包exe檔 與 dll 檔?

相信很多人google關鍵字一定是會出現ILMerge這個工具,但今天要講得不是這個工具。

今天要介紹的是一個叫"Xenocode Postbuild 2010 for .Net" *(年份可能會更新,目前最新版本為

2010(好像也有看到2013,但不確定)



首先,進入Application ->Add(加入你要的dll + exe)


一次只能放一個exe檔,但可以多個dll檔


進入virtrualize->Enable(打勾)->Runtimes->Enabled .NET runtime engine: (選擇要的版本)

(底下有SQL,但我沒用到所以就沒選擇)



最後在Output分頁這邊,有一個Single application executable(當然你要選multiple application也是可以,

但功能不同)選曲要輸出的exe檔案後->按下Build Application->完成!

然後你的程式就可以在 "非.net環境下"(沒有安裝.net framework)執行!

低調載點: .

End

2014年4月16日 星期三

[C#/winform] 資料夾小功能-開啟路徑資料夾/指定MyDocument/程式起始路徑

由於在XP / Win7 的My Document路徑是不同的,因此如果程式內要設定建立資料夾或是儲存在

My Document資料夾下的話,就必須要撰寫特殊程式碼:

Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

最後的MyDocuments可以改為MyComputer之類的....請依照需要去變更。

另外如果想要開啟指定路徑的資料夾則是:

System.Diagnostics.Process.Start(路徑)

程式起始路徑的部分是當程式放在不同資料夾時會有不同的相對路徑,因此如果要取得目前路

徑就必須要靠程式碼:

Application.StartupPath

簡單,但是實用。

End

2014年4月14日 星期一

[C#winform] 小技巧:如何新增檔名到combo box內,並檢查時否有重複?

先看程式碼

string[] Dir_sub_file = Directory.GetFileSystemEntries(要新增到combo Box項目內的資料夾內檔案名稱);
foreach (string s in Dir_sub_file)
{
      file_list.Add(Path.GetFileNameWithoutExtension(s)); //檔案名稱清單 的list<string>陣列
}

foreach (string ss in file_list)
{
      if(!comboBox_SN_1.Items.Contains(ss))
           comboBox_SN_1.Items.Add(ss);
}

首先利用Directory.GetFileSystemEntires()來取得資料夾內檔案名稱,為了不要讓後面的附檔名出現

在combo Box的內容之中,因此這邊用Path.GetFileNameWithoutExtension(string 路徑)來除去附檔名,

然後利用foreach(也可以用for)來存入我們所建立的一個list<string>陣列 叫file_list。(功用只是存檔

名清單)

第二段foreach則是把file_list內所有的string都拿出來,利用comboBox.item.Contains(string)比對是否已

經有存在在comboBox內容中,如果沒有就用.add()這方法加入comboBox的items。

End


2014年4月7日 星期一

[C#] 讀CSV檔

先看程式碼:

try
{
        using (StreamReader SR = new StreamReader(檔案路徑))
        {
            string Line;
            while ((Line = SR.ReadLine()) != null)
            {
                   string[] ReadLine_Array = Line.Split(',');
                   //這邊可以自行發揮
             }
        }
}
catch (IOException)
{ }
catch (NullReferenceException)
{ }
catch (FormatException)
{ }

先new一個StreamReader,然後建立一個暫存的String變數。

利用While() & Readline() 來讀取CSV檔,Readline()每次讀一行。

用Split(',')切割逗號(csv檔內都用逗號區隔)並放入String陣列中

之後即可應用。

End


2014年3月18日 星期二

[C#/winform] Winform Application的介面美化

測試完成示意圖


教學:   首先,下載 IrisSkin2.dll 

然後一樣 專案->加入參考->瀏覽->選擇IrisSkin2.dll

加入以後在主程式的部分寫入

namespace XXX
{
    public partial class XXX: Form
    {

        Sunisoft.IrisSkin.SkinEngine Skin = null; //這邊改Skin
        .
        .
        .
        public XXX()
        {
            InitializeComponent();

            Skin = new Sunisoft.IrisSkin.SkinEngine();
            Skin.SkinFile = @"C:\Users\Skins\MSN.ssk"; //路徑請自行更改
            Skin.SkinAllForm = true; //系統下所有Form都改為該Skin
         }
          .
          .
          .
          .
      }
  }

然後就可以了

End

2014年2月27日 星期四

[C#/winform] DataGridView 隨視窗大小變動/列的Header加入文字/隱藏行,列

DataGridView 隨視窗大小變動

將DataGridView放入Form中,調整Dock(選中間那個) = Fill即可。


DataGridView 列的Header加入文字

要讓Row的Header加入文字,只要輸入

DataGridView1.Rows[第幾列].HeaderCell.Value = 文字 即可。

隱藏行,列

DataGridView.Columns[第幾行].Visble = false; //行

DataGridView.Rows[第幾列].Visble = false; //列

小技巧,但有大功用喔!

End


2014年2月12日 星期三

[C#/winform] Notifyicon(系統列圖示) + ContextMenuStrip(右鍵選單) 設定

首先,先到工具列拉出NotifyIcon 與 ContextMenuStrip兩個工具

NotifyIcon是系統列工具,可以改變圖示(如果覺得它很醜)

ContextMenuStrip則是應用在圖示上面按滑鼠右鍵會出現的選單

如果一開始就不要讓程式show出來,請寫入

            this.WindowState = FormWindowState.Minimized;
            this.ShowInTaskbar = false;

這樣起始畫面就會縮到最小。(這段要寫再Form Load事件裡面!!)

在ContextMenuStrip當中新增一個選項ex: Exit ,接著點它兩下

進入程式部分:(這邊看要怎樣打都可以)

 this.Close();//exit代表關掉程式

最後,在Notify icon的工具欄當中把ContextMenuStrip那一欄改為你所拉進來的ContextMenuStrip的

名稱,這樣它會直接去抓那個工具,很簡單,但是很實用喔!

End


2014年2月11日 星期二

[C#/進制轉換] byte資料 轉換 ASCII碼

先看看程式碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ByteToASCII
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }

        private void button1_Click(object sender, EventArgs e)
        {
            byte[] toASCII = new byte[4];
            toASCII[0] = Convert.ToByte(textBox1.Text,10);
            toASCII[1] = Convert.ToByte(textBox2.Text,10);
            toASCII[2] = Convert.ToByte(textBox3.Text,10);
            toASCII[3] = Convert.ToByte(textBox4.Text,10);

            textBox5.Text = System.Text.Encoding.ASCII.GetString(toASCII);
        }
    }
}

先new一個byte陣列,利用Convert.ToByte(String,多少進位)來轉換,存如byte陣列當中

之後用Sytem.Text.Encoding.ASCII.GetString(byte陣列) 即可轉換

End

2014年2月6日 星期四

[C#/winform] 讀寫ini檔

ini檔為windows內常用來儲存setting的檔案,C#範例如下。

dllimport為必須要的,會動態連結到system32的檔案,


WritePrivateProfileString(string section, string key, string val, string filePath)寫入ini檔案


GetPrivateProfileString( string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString,uint nSize, string lpFileName)讀取ini檔案

P.S.此範例為自動抓取RS-232 port放入comboBox1內,尚未寫完,但讀寫ini的部分是完整的

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;

namespace Test_INI
{
    public partial class Form1 : Form
    {
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
 
        public Form1()
        {
            InitializeComponent();

            string[] port_list = SerialPort.GetPortNames();
            foreach (string port in port_list)
            {
                //MessageBox.Show("本機可用serial port: " + port); //測試用
                comboBox1.Items.Add(port);
            }
            //當select port index換的時候 ,加入WritePrivateProfileString("Port Name", "name", 選擇的port
            //string, @"D:\myConfig.ini");//寫入ini檔
            WritePrivateProfileString("Port Name", "name", "COM1", @"D:\myConfig.ini");//寫入ini檔
            WritePrivateProfileString("ModBus", "number", "1", @"D:\myConfig.ini");//寫入ini檔
            WritePrivateProfileString("ModBus", "number", "2", @"D:\myConfig.ini");//寫入ini檔
        }

        private void button1_Click(object sender, EventArgs e)
        {
            StringBuilder data = new StringBuilder(255);
            GetPrivateProfileString("Port Name", "name", "NA", data, 255,          
            @"D:\myConfig.ini");//section/key/def/ stringbuilder的變數/長度/路徑
            MessageBox.Show(data.ToString());
        }
    }
}

[C#/winform] 不同解析度調整視窗大小

利用DPI取得螢幕解析度比例,進而改變WinForm的大小

如上,DPI可能為
DPI大小百分比
96100%
120125%
144150%

廢話不多說

// 找出字體大小,並算出比例
float dpiX, dpiY;
Graphics graphics = this.CreateGraphics();
dpiX = graphics.DpiX;
dpiY = graphics.DpiY;
int intPercent = (dpiX == 96) ? 100 : (dpiX == 120) ? 125 : 150;

// 針對字體變更Form的大小
this.Height = this.Height * intPercent / 100;
this.Width = this.Width * intPercent / 100;


end.