DataGridView 隨視窗大小變動
將DataGridView放入Form中,調整Dock(選中間那個) = Fill即可。
DataGridView 列的Header加入文字
要讓Row的Header加入文字,只要輸入
DataGridView1.Rows[第幾列].HeaderCell.Value = 文字 即可。
隱藏行,列
DataGridView.Columns[第幾行].Visble = false; //行
DataGridView.Rows[第幾列].Visble = false; //列
小技巧,但有大功用喔!
End
2014年2月27日 星期四
[C#/win32 API] SendMessage() 與 PostMessage()
網路上比較少SendMessage()跟PostMessage資料
先給SendMessage範例
SendMessage會等到接收端check後才會繼續執行,而PostMessage則是丟入訊息queue,繼續做。
以下範例都要先加入 using System.Runtime.InteropServices;
SendMessage A端(控制端):
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;
namespace TestA
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
uint MSG_SHOW = RegisterWindowMessage("Show Message");
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
public Form1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
IntPtr form_name = FindWindow(null, "要控制的視窗元件名稱(text,不是name)");//找B的IntPtr 用來代表指標或控制代碼
if (form_name != IntPtr.Zero)
{
try
{
int iNum = 9527;
SendMessage(form_name, MSG_SHOW, iNum, IntPtr.Zero);
}
catch (Exception)
{
}
}
}
}
}
PostMessage A端(呼叫端):
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;
namespace postmessager
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
private void post()
{
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr ptr = FindWindow(null, "post messager B");
if (ptr != IntPtr.Zero)
{
int msg = 9527;
PostMessage(ptr, msg, IntPtr.Zero, IntPtr.Zero);
}
}
}
}
先給SendMessage範例
以下範例都要先加入 using System.Runtime.InteropServices;
SendMessage A端(控制端):
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;
namespace TestA
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
uint MSG_SHOW = RegisterWindowMessage("Show Message");
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
public Form1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
IntPtr form_name = FindWindow(null, "要控制的視窗元件名稱(text,不是name)");//找B的IntPtr 用來代表指標或控制代碼
if (form_name != IntPtr.Zero)
{
try
{
int iNum = 9527;
SendMessage(form_name, MSG_SHOW, iNum, IntPtr.Zero);
}
catch (Exception)
{
}
}
}
}
}
SendMessage B端(接收端):
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;
namespace TestB
{
public partial class TestB_1 : Form
{
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
uint MSG_SHOW = RegisterWindowMessage("Show Message");
public TestB_1()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == MSG_SHOW)
{
label1.Text = (string)m.WParam.ToString();
}
base.WndProc(ref m);
}
}
}
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;
namespace postmessager
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
private void post()
{
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr ptr = FindWindow(null, "post messager B");
if (ptr != IntPtr.Zero)
{
int msg = 9527;
PostMessage(ptr, msg, IntPtr.Zero, IntPtr.Zero);
}
}
}
}
PostMessage B端(接收端):
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;
namespace PostmessagerB
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 9527)//m.Msg == MSG_SHOW
{
//label1.Text = (string)m.WParam.ToString();
MessageBox.Show("9527");
}
base.WndProc(ref m);
}
}
}
至於為何可以使用SendMessage(),PostMessage(),FindWindow(),RegisterWindowMessage(),都是要先
import user32.dll (也就是[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 後面為參數)
然後接收端使用WndProc (WindowProcess,我個人理解縮寫函意)去接收。
大部分程式碼也是參考網路上的,但大家都抄來抄去,而且我有修改程式碼,所以就不註明出處了(因為也不知道原始是誰的),當然我的版本是比較精簡化。
End
End
2014年2月19日 星期三
[C#/winform] 主Form / 副 Form 如何製作+連結2個Form
在VS2012裡面按 專案-> 加入windows form
你設定的檔名ex : form2
回到主Form,在要顯示的地方加入
Form2 frm2(這名稱可以改) = new Form2();
frm2.showdialog(this); //show 副form
this.show(); //回到主form
即可。
你設定的檔名ex : form2
回到主Form,在要顯示的地方加入
Form2 frm2(這名稱可以改) = new Form2();
frm2.showdialog(this); //show 副form
this.show(); //回到主form
即可。
[C#/Error] 不一致的存取範圍: 欄位型別 ...... 比欄位 ..... 存取範圍低
通常初學者寫Class不會特別宣告型別
但如果你宣告
public static Class名稱;
public Form
{
....
....
}
Class 名稱
{
......
}
這樣就有問題了!! 因為基本設定 Class沒加任何型別 = internal(內部可用)
Public > internal 所以 造成 "不一致的存取範圍: 欄位型別 ...... 比欄位 ..... 存取範圍低"的Error!
public static Class名稱;
public Form
{
....
....
}
public Class 名稱
{
......
}
這樣才對
End
但如果你宣告
public static Class名稱;
public Form
{
....
....
}
Class 名稱
{
......
}
這樣就有問題了!! 因為基本設定 Class沒加任何型別 = internal(內部可用)
Public > internal 所以 造成 "不一致的存取範圍: 欄位型別 ...... 比欄位 ..... 存取範圍低"的Error!
public static Class名稱;
public Form
{
....
....
}
public Class 名稱
{
......
}
這樣才對
End
[C#] List的基本用法
在寫程式常常會遇到要動態陣列,C#也很貼心的做了一個功能----泛型List<T>
但我想主要不是用在這邊....沒關係,還是講解一下List的用法
一開始一定就是
List<任意型態> 名稱 = new List<跟前面一樣的任意型態>(); //new給它一個空間
然後就可以在迴圈裡面丟給它值(它可以任意變動長度)
丟值的方法為: 名稱.Add(值);
如果要從中取出值就跟陣列一樣
名稱[0] (陣列位置可以改,這邊只是範例)
如果要長度 :名稱.Count 就會跟平常的.Length一樣囉!
範例:
List<byte> modbus = new List<byte>();
for (int i = 0; i < 30; i++)
{
if (Modbus_save[i] == true) //這邊只是設一個條件而已
{
modbus.Add(Convert.ToByte(i)); //把i轉byte型態,存入List<T>
}
}
End
但我想主要不是用在這邊....沒關係,還是講解一下List的用法
一開始一定就是
List<任意型態> 名稱 = new List<跟前面一樣的任意型態>(); //new給它一個空間
然後就可以在迴圈裡面丟給它值(它可以任意變動長度)
丟值的方法為: 名稱.Add(值);
如果要從中取出值就跟陣列一樣
名稱[0] (陣列位置可以改,這邊只是範例)
如果要長度 :名稱.Count 就會跟平常的.Length一樣囉!
範例:
List<byte> modbus = new List<byte>();
for (int i = 0; i < 30; i++)
{
if (Modbus_save[i] == true) //這邊只是設一個條件而已
{
modbus.Add(Convert.ToByte(i)); //把i轉byte型態,存入List<T>
}
}
End
2014年2月18日 星期二
[C#/winform] Form與Form之間 傳值
有許多方法可以傳值,包括Properties/Class/ini檔..等
這邊講兩個
1.Properties
使用時機: 需要儲存使用者設定時。
使用方法: 先到專案-> xxx屬性->設定,設定幾個需要使用的變數(型態要調好)
然後Form2內將變數代入Properties.Settings.Default.(設的變數名稱),
接著再去Form1內將Properties.Settings.Default.(設的變數名稱) 帶回form1(設一個新的變數去接)
記得要儲存使用者設定要加入Properties.Settings.Default.Save();
2.Class
使用時機: 滿廣泛的,但關掉無法儲存
使用方法: Form2內設一個public 變數
ex:
Public int a {get; set;}
public Form2{
....
}
回到Form1以後就可以用了,記得要寫在ShowDialog();的下方
Form2 frm2 = new Form2();
frm2.ShowDialog(this);
(寫在這邊)
當然要接值的話,型別也要對就是了。
End
這邊講兩個
1.Properties
使用時機: 需要儲存使用者設定時。
使用方法: 先到專案-> xxx屬性->設定,設定幾個需要使用的變數(型態要調好)
然後Form2內將變數代入Properties.Settings.Default.(設的變數名稱),
接著再去Form1內將Properties.Settings.Default.(設的變數名稱) 帶回form1(設一個新的變數去接)
記得要儲存使用者設定要加入Properties.Settings.Default.Save();
2.Class
使用時機: 滿廣泛的,但關掉無法儲存
使用方法: Form2內設一個public 變數
ex:
Public int a {get; set;}
public Form2{
....
}
回到Form1以後就可以用了,記得要寫在ShowDialog();的下方
Form2 frm2 = new Form2();
frm2.ShowDialog(this);
(寫在這邊)
當然要接值的話,型別也要對就是了。
End
2014年2月14日 星期五
[C#/winform] smtp傳送電子郵件(email)
using System.Net.Mail;
using System.Net;
class Email
{
public string From {get;set; }
public string To { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public string Account { get; set; }
public string Password { get; set; }
public string Server { get; set; }
public string Port { get; set; }
public void Send_email()
{
//這邊先設定From,To,Subject,Body,Account,Password,Server,Port
SmtpClient theSmtpClient = new SmtpClient(Server);
NetworkCredential networkcredential = new NetworkCredential(Account, Password);//帳密
theSmtpClient.UseDefaultCredentials = false;
theSmtpClient.Credentials = networkcredential;
int Int_port = Convert.ToInt32(Port);
if (Int_port == 587)
{
theSmtpClient.EnableSsl = true;
}
else//不是587 就是 25
{
theSmtpClient.EnableSsl = false;
}
theSmtpClient.Port = Int_port;
try
{
theSmtpClient.Send(From, To, Subject, Body);
}
catch (Exception)
{
}
}
}
十分簡單,不過要注意的地方就是Port在有SSL加密認證的環境下要用587(ex:gmail),沒有的話則用25即可,然後Using要加入net / net.mail
End
using System.Net;
class Email
{
public string From {get;set; }
public string To { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public string Account { get; set; }
public string Password { get; set; }
public string Server { get; set; }
public string Port { get; set; }
public void Send_email()
{
//這邊先設定From,To,Subject,Body,Account,Password,Server,Port
SmtpClient theSmtpClient = new SmtpClient(Server);
NetworkCredential networkcredential = new NetworkCredential(Account, Password);//帳密
theSmtpClient.UseDefaultCredentials = false;
theSmtpClient.Credentials = networkcredential;
int Int_port = Convert.ToInt32(Port);
if (Int_port == 587)
{
theSmtpClient.EnableSsl = true;
}
else//不是587 就是 25
{
theSmtpClient.EnableSsl = false;
}
theSmtpClient.Port = Int_port;
try
{
theSmtpClient.Send(From, To, Subject, Body);
}
catch (Exception)
{
}
}
}
十分簡單,不過要注意的地方就是Port在有SSL加密認證的環境下要用587(ex:gmail),沒有的話則用25即可,然後Using要加入net / net.mail
End
2014年2月13日 星期四
[C#/winform] 呼叫外部程式(傳入參數) + 不會顯示出來 + 結束強制關閉程式
本篇分成三部份來講
a)呼叫外部程式
//呼叫程式(啟動)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
namespace Activate_exe
{
static class Program
{
/// <summary>
/// 應用程式的主要進入點。
/// </summary>
[STAThread]
static void Main()
{
string target = 目標路徑;
ProcessStartInfo pInfo = new ProcessStartInfo(target);
pInfo.Arguments = "我是參數";
using (Process p = new Process())
{
p.StartInfo = pInfo;
p.Start();
}
}
}
}
//主程式(被呼叫)
//在Program.cs內部
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace (被呼叫的程式,名稱自行更改)
{
static class Program
{
/// <summary>
/// 應用程式的主要進入點。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length == 0)
{
Application.Run(new Form1());
}
else
{
Application.Run(new Form1(args[0].ToString()));
}
}
}
}
呼叫程式十分簡單,也不需要用到winform,就直接寫在Program.cs即可
一開始記得要加入"using System.Diagnostics;"不然ProcessStartInfo 沒法用,
new一個ProcessStartInfo(要呼叫的程式路徑),然後 ProcessStartInfo.Argument內就是要傳的參數。
(參數遇到空格 疑似可以用\" (http://blogs.msdn.com/b/csharpfaq/archive/2004/03/12/88415.aspx)來解決)
傳多個參數,就是使用空格作為分隔 參數A空格B,在Form1値得注意的地方就是有兩個多載,當
沒有參數傳來的時後就用Form1(),有則Form1(args[])
-----------------------------------------------------------------------------------------------------------
被呼叫的程式要接參數,所以main(string[] args
主程式//Form1.cs
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 Argument_IN_exe
{
public partial class Form1 : Form
{
private string _args;
public Form1()
{
InitializeComponent();
}
public Form1(string value)
{
InitializeComponent();
if (!string.IsNullOrEmpty(value))
{
_args = value;
MessageBox.Show(_args);
}
}
}
}
b)不會顯示出來
要讓程式一開啟就不顯示出來,目前只知道這個方法(最小化+不顯是在系統列)
寫在Form load事件當中,一讀就縮最小,但是有個問題就是你無法停止它(所以才需要
c.強制關閉程式)
private void Form1_Load_1(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
this.Hide();
}
private void Form1_Shown(object sender, EventArgs e)
{
this.Hide();
}
c)結束強制關閉程式
光有Close()是不夠的,可以試試看Ctrl+Alt+Del,會發現沒有全部關完。
加入Enviroment這行吧!
this.Close();
Environment.Exit(Environment.ExitCode);
參考: http://www.dotblogs.com.tw/atowngit/archive/2009/12/26/12681.aspx
a)呼叫外部程式
//呼叫程式(啟動)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
namespace Activate_exe
{
static class Program
{
/// <summary>
/// 應用程式的主要進入點。
/// </summary>
[STAThread]
static void Main()
{
string target = 目標路徑;
ProcessStartInfo pInfo = new ProcessStartInfo(target);
pInfo.Arguments = "我是參數";
using (Process p = new Process())
{
p.StartInfo = pInfo;
p.Start();
}
}
}
}
//主程式(被呼叫)
//在Program.cs內部
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace (被呼叫的程式,名稱自行更改)
{
static class Program
{
/// <summary>
/// 應用程式的主要進入點。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length == 0)
{
Application.Run(new Form1());
}
else
{
Application.Run(new Form1(args[0].ToString()));
}
}
}
}
呼叫程式十分簡單,也不需要用到winform,就直接寫在Program.cs即可
一開始記得要加入"using System.Diagnostics;"不然ProcessStartInfo 沒法用,
new一個ProcessStartInfo(要呼叫的程式路徑),然後 ProcessStartInfo.Argument內就是要傳的參數。
(參數遇到空格 疑似可以用\" (http://blogs.msdn.com/b/csharpfaq/archive/2004/03/12/88415.aspx)來解決)
傳多個參數,就是使用空格作為分隔 參數A空格B,在Form1値得注意的地方就是有兩個多載,當
沒有參數傳來的時後就用Form1(),有則Form1(args[])
-----------------------------------------------------------------------------------------------------------
被呼叫的程式要接參數,所以main(string[] args
主程式//Form1.cs
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 Argument_IN_exe
{
public partial class Form1 : Form
{
private string _args;
public Form1()
{
InitializeComponent();
}
public Form1(string value)
{
InitializeComponent();
if (!string.IsNullOrEmpty(value))
{
_args = value;
MessageBox.Show(_args);
}
}
}
}
b)不會顯示出來
要讓程式一開啟就不顯示出來,目前只知道這個方法(最小化+不顯是在系統列)
寫在Form load事件當中,一讀就縮最小,但是有個問題就是你無法停止它(所以才需要
c.強制關閉程式)
private void Form1_Load_1(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
this.Hide();
}
private void Form1_Shown(object sender, EventArgs e)
{
this.Hide();
}
c)結束強制關閉程式
光有Close()是不夠的,可以試試看Ctrl+Alt+Del,會發現沒有全部關完。
加入Enviroment這行吧!
this.Close();
Environment.Exit(Environment.ExitCode);
參考: http://www.dotblogs.com.tw/atowngit/archive/2009/12/26/12681.aspx
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
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#/Serialize] 簡易版本-Serailize/Deserialize
上一篇序列化/反序列化比較難,這次寫一點簡單的。
首先一樣先建一個類別庫(新增專案->類別庫)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Solar_stucture
{
[Serializable]
public class Solar_read
{
public byte Adress = 0;
public byte Function_code = 0;
public byte Byte_count = 0;
}
}
然後建製(F9) 會產生錯誤,很正常。但不是錯誤。(在Debug資料夾內會有.dll檔)
接著,開個新的專案。然後 專案->加入參考...(瀏覽->選剛剛產生的dll檔)
在主程式(或任何你想要加的地方)加入
Solar_read Read_protocol = new Solar_read();
然後使用Read_protocol.Adress,你會發現可以使用!!
沒錯,就把東西存進去(型別要對)
都加完了以後,開始寫入檔案。
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("Read Protocol.dat", FileMode.Create, FileAccess.Write, FileShare.Read);
formatter.Serialize(stream, Read_protocol);
stream.Close();
記得dll檔那邊要有[Serializable]不然這邊執行上會出現serialize的異常。序列化到此結束!
基本的反序列化也十分簡單:
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 Solar_stucture;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace SolarControl_Front
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(序列化存的檔案路徑, FileMode.Open, FileAccess.Read, FileShare.Read);
Solar_read read = (Solar_read)formatter.Deserialize(stream);
MessageBox.Show(read.Adress.ToString());
stream.Close();
}
}
}
首先一樣先建一個類別庫(新增專案->類別庫)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Solar_stucture
{
[Serializable]
public class Solar_read
{
public byte Adress = 0;
public byte Function_code = 0;
public byte Byte_count = 0;
}
}
然後建製(F9) 會產生錯誤,很正常。但不是錯誤。(在Debug資料夾內會有.dll檔)
接著,開個新的專案。然後 專案->加入參考...(瀏覽->選剛剛產生的dll檔)
在主程式(或任何你想要加的地方)加入
Solar_read Read_protocol = new Solar_read();
然後使用Read_protocol.Adress,你會發現可以使用!!
沒錯,就把東西存進去(型別要對)
都加完了以後,開始寫入檔案。
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("Read Protocol.dat", FileMode.Create, FileAccess.Write, FileShare.Read);
formatter.Serialize(stream, Read_protocol);
stream.Close();
記得dll檔那邊要有[Serializable]不然這邊執行上會出現serialize的異常。序列化到此結束!
基本的反序列化也十分簡單:
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 Solar_stucture;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace SolarControl_Front
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(序列化存的檔案路徑, FileMode.Open, FileAccess.Read, FileShare.Read);
Solar_read read = (Solar_read)formatter.Deserialize(stream);
MessageBox.Show(read.Adress.ToString());
stream.Close();
}
}
}
一樣的東西,只是變成Deserialize(Stream stream),接的格式是用你所創建的Class格式喔!
MessageBox只是確認有弄對而已。 Over
MessageBox只是確認有弄對而已。 Over
[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
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月10日 星期一
[C#/Serialize] 在不同檔案間傳遞結構(structure)利用Serialize和Deserialize
首先必須先創建一個"類別庫"(新增->類別庫 in VS2012)
一定要有關鍵字[Serializable]否則無法,然後建立一個Struct
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.ComponentModel;
namespace PassingStruct
{
public class Class1
{
}
[Serializable]
public struct MemberList
{
private BindingList<Member> _MemberCollection;
public BindingList<Member> MemberCollection
{
get
{
if (this._MemberCollection == null)
this._MemberCollection = new BindingList<Member>();
return this._MemberCollection;
}
}
}
[Serializable]
public struct Member
{
public int ID { get; set; }
public int age { get; set; }
public string name { get; set; }
public int number { get; set; }
public string sex { get; set; }
}
}
編譯時會產生錯誤訊息,但其實還是成功(在Debug資料夾內)會有一個dll檔產生。
OK,到這邊,需要將dll檔加入參考到要序列化的程式碼。
以下為序列化程式碼
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.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using PassingStruct;
namespace Binary_filestreame
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
PassingStruct.MemberList list = CreateClass();
SerializeToBinary("list.dat", list);
}
public PassingStruct.MemberList CreateClass()
{
PassingStruct.MemberList list = new PassingStruct.MemberList();
list.MemberCollection.Add(new PassingStruct.Member() { ID = 1, age = 18, name = "paul walker", number = 999, sex = "male" });
list.MemberCollection.Add(new PassingStruct.Member() { ID = 2, age = 20, name = "jonathan brewster", number = 123, sex = "female" });
return list;
}
public static void SerializeToBinary(string FileName, object Object)
{
Stream stream = null;
IFormatter/*用於格式化已經序列化的東西*/ format = new BinaryFormatter();//以二進位格式序列化和還原序列化物件
try
{
stream = new FileStream(FileName,FileMode.Create,FileAccess.Write,FileShare.Read);
format.Serialize(stream, Object);
}
catch(Exception ex)
{
throw ex;
}
finally
{
stream.Close();
}
}
private void button2_Click(object sender, EventArgs e)
{
PassingStruct.MemberList list = DeserializeFromBinary<PassingStruct.MemberList>("list.dat");
}
public static T DeserializeFromBinary<T>(string FileName)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = null;
try
{
stream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
object obj = formatter.Deserialize(stream);
if (obj == null)
return default(T);
else
return (T)obj;
}
catch (Exception ex)
{
throw ex;
}
finally
{
stream.Close();
}
}
}
}
注意到在using這邊
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using PassingStruct;//這個就是dll檔,除了在Visual Studio專案裡面選擇 專案->加入參考->瀏覽->dll檔,還要加入這一行
然後,序列化基本上就完成了。接著就是反序列化:(以下為反序列化程式碼)
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.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using PassingStruct;
namespace serialize_transfer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//File.wr
}
public static T DeserializeFromBinary<T>(string FilePath)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = null;
try
{
stream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
object obj = formatter.Deserialize(stream);//問題出在這邊
if (obj == null)
return default(T);
else
return (T)obj;
}
catch (Exception ex)
{
throw ex;
}
finally
{
stream.Close();
}
}
private void button1_Click(object sender, EventArgs e)
{
PassingStruct.MemberList list = DeserializeFromBinary<PassingStruct.MemberList>(@"C:\Users\daniel\Dropbox\Visual Studio 2012\Projects\Binary_filestreame\Binary_filestreame\bin\Debug\list.dat");
}
}
}
同樣也需要加入參考以及+using的程式碼 記得反序列化路徑要弄對就好了。
應用的部分,可使用在DataGridView上面
BindingSource Source = new BindingSource();
public void Form1_Load(object sender, EventArgs e)
{
this.Source.DataSource = CreateClass().MemberCollection;
this.dataGridView1.DataSource = this.Source;
this.bindingNavigator1.BindingSource = this.Source;
this.textBox1.DataBindings.Add("Text", this.Source, "ID");
this.textBox2.DataBindings.Add("Text", this.Source, "name");
this.textBox3.DataBindings.Add("Text", this.Source, "age");
this.textBox4.DataBindings.Add("Text", this.Source, "phone");
this.textBox5.DataBindings.Add("Text", this.Source, "sex");
}
End
參考資料: 余小章.net教學
一定要有關鍵字[Serializable]否則無法,然後建立一個Struct
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.ComponentModel;
namespace PassingStruct
{
public class Class1
{
}
[Serializable]
public struct MemberList
{
private BindingList<Member> _MemberCollection;
public BindingList<Member> MemberCollection
{
get
{
if (this._MemberCollection == null)
this._MemberCollection = new BindingList<Member>();
return this._MemberCollection;
}
}
}
[Serializable]
public struct Member
{
public int ID { get; set; }
public int age { get; set; }
public string name { get; set; }
public int number { get; set; }
public string sex { get; set; }
}
}
編譯時會產生錯誤訊息,但其實還是成功(在Debug資料夾內)會有一個dll檔產生。
OK,到這邊,需要將dll檔加入參考到要序列化的程式碼。
以下為序列化程式碼
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.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using PassingStruct;
namespace Binary_filestreame
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
PassingStruct.MemberList list = CreateClass();
SerializeToBinary("list.dat", list);
}
public PassingStruct.MemberList CreateClass()
{
PassingStruct.MemberList list = new PassingStruct.MemberList();
list.MemberCollection.Add(new PassingStruct.Member() { ID = 1, age = 18, name = "paul walker", number = 999, sex = "male" });
list.MemberCollection.Add(new PassingStruct.Member() { ID = 2, age = 20, name = "jonathan brewster", number = 123, sex = "female" });
return list;
}
public static void SerializeToBinary(string FileName, object Object)
{
Stream stream = null;
IFormatter/*用於格式化已經序列化的東西*/ format = new BinaryFormatter();//以二進位格式序列化和還原序列化物件
try
{
stream = new FileStream(FileName,FileMode.Create,FileAccess.Write,FileShare.Read);
format.Serialize(stream, Object);
}
catch(Exception ex)
{
throw ex;
}
finally
{
stream.Close();
}
}
private void button2_Click(object sender, EventArgs e)
{
PassingStruct.MemberList list = DeserializeFromBinary<PassingStruct.MemberList>("list.dat");
}
public static T DeserializeFromBinary<T>(string FileName)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = null;
try
{
stream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
object obj = formatter.Deserialize(stream);
if (obj == null)
return default(T);
else
return (T)obj;
}
catch (Exception ex)
{
throw ex;
}
finally
{
stream.Close();
}
}
}
}
注意到在using這邊
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using PassingStruct;//這個就是dll檔,除了在Visual Studio專案裡面選擇 專案->加入參考->瀏覽->dll檔,還要加入這一行
然後,序列化基本上就完成了。接著就是反序列化:(以下為反序列化程式碼)
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.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using PassingStruct;
namespace serialize_transfer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//File.wr
}
public static T DeserializeFromBinary<T>(string FilePath)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = null;
try
{
stream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
object obj = formatter.Deserialize(stream);//問題出在這邊
if (obj == null)
return default(T);
else
return (T)obj;
}
catch (Exception ex)
{
throw ex;
}
finally
{
stream.Close();
}
}
private void button1_Click(object sender, EventArgs e)
{
PassingStruct.MemberList list = DeserializeFromBinary<PassingStruct.MemberList>(@"C:\Users\daniel\Dropbox\Visual Studio 2012\Projects\Binary_filestreame\Binary_filestreame\bin\Debug\list.dat");
}
}
}
同樣也需要加入參考以及+using的程式碼 記得反序列化路徑要弄對就好了。
應用的部分,可使用在DataGridView上面
BindingSource Source = new BindingSource();
public void Form1_Load(object sender, EventArgs e)
{
this.Source.DataSource = CreateClass().MemberCollection;
this.dataGridView1.DataSource = this.Source;
this.bindingNavigator1.BindingSource = this.Source;
this.textBox1.DataBindings.Add("Text", this.Source, "ID");
this.textBox2.DataBindings.Add("Text", this.Source, "name");
this.textBox3.DataBindings.Add("Text", this.Source, "age");
this.textBox4.DataBindings.Add("Text", this.Source, "phone");
this.textBox5.DataBindings.Add("Text", this.Source, "sex");
}
End
參考資料: 余小章.net教學
2014年2月7日 星期五
[C#/winform] RS-232/SerialPort 傳送及接收
1.先從工具箱拉SerialPort元件(要記得程式碼加入System.IO.Ports)
2.點選元件可以調整BaudRate.DataBit.ParityBit.HandShake...等
3.也可以從程式碼中新增: serialPort1 = new SerialPort(COM幾(String), 9600, Parity.None, 8, StopBits.One);
4.如果要抓取電腦現有的COM,可以使用string[] port_name = SerialPort.GetPortName();
可以用foreach() loop + comboBox的add來新增到comboBox裡面
5.讀取部分
private byte[] Port_read()
{
//---------------------------讀取部分---------------------------------//
int B2R = serialPort1.BytesToRead;//有多少
byte[] Buffer = new byte[B2R];//new多少byte 陣列
if (B2R > 0)
{
serialPort1.Read(Buffer, 0, B2R);//有多少就讀入多少(共85byte)
}
return Buffer;
//---------------------------讀取部分-End------------------------------//
}
6.寫入部分
//---------------------------寫入部分----------------------------------//
//先檢查有幾個modbus,
try
{
serialPort1.Write(byte陣列, 0, 寫多少byte);
}
catch (InvalidOperationException)
{
MessageBox.Show("關閉通訊埠");//關閉通訊埠
}
catch (IOException IOE)
{
MessageBox.Show(IOE.Message);
MessageBox.Show("IO錯誤");//IO exception
}
大致上就完成簡單的通訊程式
其餘比較有用的:
System.Text.Encoding.Default.GetBytes(String); //string轉byte[]
System.Text.Encoding.Default.GetString(byte[]);//byte[]轉String
2.點選元件可以調整BaudRate.DataBit.ParityBit.HandShake...等
3.也可以從程式碼中新增: serialPort1 = new SerialPort(COM幾(String), 9600, Parity.None, 8, StopBits.One);
4.如果要抓取電腦現有的COM,可以使用string[] port_name = SerialPort.GetPortName();
可以用foreach() loop + comboBox的add來新增到comboBox裡面
5.讀取部分
private byte[] Port_read()
{
//---------------------------讀取部分---------------------------------//
int B2R = serialPort1.BytesToRead;//有多少
byte[] Buffer = new byte[B2R];//new多少byte 陣列
if (B2R > 0)
{
serialPort1.Read(Buffer, 0, B2R);//有多少就讀入多少(共85byte)
}
return Buffer;
//---------------------------讀取部分-End------------------------------//
}
6.寫入部分
//---------------------------寫入部分----------------------------------//
//先檢查有幾個modbus,
try
{
serialPort1.Write(byte陣列, 0, 寫多少byte);
}
catch (InvalidOperationException)
{
MessageBox.Show("關閉通訊埠");//關閉通訊埠
}
catch (IOException IOE)
{
MessageBox.Show(IOE.Message);
MessageBox.Show("IO錯誤");//IO exception
}
大致上就完成簡單的通訊程式
其餘比較有用的:
System.Text.Encoding.Default.GetBytes(String); //string轉byte[]
System.Text.Encoding.Default.GetString(byte[]);//byte[]轉String
[C#] Class小記 - 以 CRC 16為例
先看程式碼,如下
class CRC_16
{
public byte CRC_1 { get; set; }
public byte CRC_2 { get; set; }
public void CRC16_counter(byte[] data, int CRC_length) //跑兩個 1.送出去產生CRC(length = 6) 產生後 = 8
{ // 2.接收時驗證CRC(length = 83) 產生後 = 85
ushort CRCFull = 0xFFFF;
byte CRChigh = 0xFF, CRClow = 0xFF;
char CRC_LSB;
for (int i = 0; i < CRC_length; i++)
{
CRCFull = (ushort)(CRCFull ^ data[i]); //指令的第i組數字與CRCFull做XOR
for (int j = 0; j < 8; j++)//8bit,所以跑八次
{
CRC_LSB = (char)(CRCFull & 0x00000001);//取得最後一個位元的值
CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF); //右移一位,第一位補0
//檢查
if (CRC_LSB == 0) //如果右移的值為0
{
//就把剛剛右移+第一位補零的數值存入暫存(不過已經做了,這邊只是註解)
}
if (CRC_LSB == 1) // 如果右移的值為1
{
CRCFull = (ushort)(CRCFull ^ 0xA001); //跟0xA001去做XOR,存入暫存器
}
}
}
//跑完要讓高低register對調
//CRChigh = (byte)((CRCFull >> 8) & 0xFF); //右移8Bit,也就是變成低位元,跟FF(1111 1111)做& 0還是0 1還是1
//CRClow = (byte)(CRCFull & 0xFF); //低的變成高的
CRChigh = (byte)(CRCFull >> 8); //右移8Bit,也就是變成低位元,跟FF(1111 1111)做& 0還是0 1還是1,不用&0xff也可
CRClow = (byte)CRCFull; //低的變成高的,不用&0xff也可
if (CRC_length == 6)
{
CRC_2 = CRChigh;//現在是低
CRC_1 = CRClow; //現在是高
}
if (CRC_length == 83)
{
CRC_2 = CRChigh;//現在是低
CRC_1 = CRClow; //現在是高
}
}
}
本例Protocol有兩種1.傳送(8byte)2.接收(85byte)
因此先用6byte 算出CRC(最後2byte) = 8 / 83byte 算出CRC(最後2byte) = 85,
用以驗證CRC-16是否正確。
Class部份假如要使用到CRC_1,CRC_2 則需要 這樣呼叫
1.先new好Class
CRC_16 CRC = new CRC_16();
2.存取Class內部資料
CRC.CRC_1 ,CRC.CRC_2
3.如果內部將CRC_1宣告成 public static .... ,則呼叫需改為
namespace名稱.Class名稱.CRC_1
class CRC_16
{
public byte CRC_1 { get; set; }
public byte CRC_2 { get; set; }
public void CRC16_counter(byte[] data, int CRC_length) //跑兩個 1.送出去產生CRC(length = 6) 產生後 = 8
{ // 2.接收時驗證CRC(length = 83) 產生後 = 85
ushort CRCFull = 0xFFFF;
byte CRChigh = 0xFF, CRClow = 0xFF;
char CRC_LSB;
for (int i = 0; i < CRC_length; i++)
{
CRCFull = (ushort)(CRCFull ^ data[i]); //指令的第i組數字與CRCFull做XOR
for (int j = 0; j < 8; j++)//8bit,所以跑八次
{
CRC_LSB = (char)(CRCFull & 0x00000001);//取得最後一個位元的值
CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF); //右移一位,第一位補0
//檢查
if (CRC_LSB == 0) //如果右移的值為0
{
//就把剛剛右移+第一位補零的數值存入暫存(不過已經做了,這邊只是註解)
}
if (CRC_LSB == 1) // 如果右移的值為1
{
CRCFull = (ushort)(CRCFull ^ 0xA001); //跟0xA001去做XOR,存入暫存器
}
}
}
//跑完要讓高低register對調
//CRChigh = (byte)((CRCFull >> 8) & 0xFF); //右移8Bit,也就是變成低位元,跟FF(1111 1111)做& 0還是0 1還是1
//CRClow = (byte)(CRCFull & 0xFF); //低的變成高的
CRChigh = (byte)(CRCFull >> 8); //右移8Bit,也就是變成低位元,跟FF(1111 1111)做& 0還是0 1還是1,不用&0xff也可
CRClow = (byte)CRCFull; //低的變成高的,不用&0xff也可
if (CRC_length == 6)
{
CRC_2 = CRChigh;//現在是低
CRC_1 = CRClow; //現在是高
}
if (CRC_length == 83)
{
CRC_2 = CRChigh;//現在是低
CRC_1 = CRClow; //現在是高
}
}
}
本例Protocol有兩種1.傳送(8byte)2.接收(85byte)
因此先用6byte 算出CRC(最後2byte) = 8 / 83byte 算出CRC(最後2byte) = 85,
用以驗證CRC-16是否正確。
Class部份假如要使用到CRC_1,CRC_2 則需要 這樣呼叫
1.先new好Class
CRC_16 CRC = new CRC_16();
2.存取Class內部資料
CRC.CRC_1 ,CRC.CRC_2
3.如果內部將CRC_1宣告成 public static .... ,則呼叫需改為
namespace名稱.Class名稱.CRC_1
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());
}
}
}
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 | 大小百分比 |
96 | 100% |
120 | 125% |
144 | 150% |
廢話不多說
// 找出字體大小,並算出比例
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.