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

2011年7月21日 星期四

一些在Windows Installer時,撰寫Registry會用到的保留字

最常用的應該就是
[TARGETDIR] //此保留字,表示程式安裝的路徑

其他... 嗯... 太多了自己看

http://msdn.microsoft.com/zh-tw/library/aa370905.aspx

2009年3月24日 星期二

於程式執行階段實現 Alt+Tab 切換視窗功能(使用Win32 API)

這裡做一個簡單的測試,我們用TestSwitch程式執行的一個名為Form1.exe的視窗程式,當Form1.exe啟動後我們利用Alt+Tab或其他方式,將Form1.exe的視窗蓋住了,這時我們希望在TestSwitch程式中將Form1.exe的視窗再帶到螢幕的最前面,該怎麼做呢?


//要使用Win32 API前需要先加入

using System.Runtime.InteropServices;

public class TestSwitch
{
 //然後使用下面兩的API

 [DllImport("user32.dll")]
 static extern IntPtr SetActiveWindow(IntPtr hWnd);

 [DllImport("user32.dll")]
 [return: MarshalAs(UnmanagedType.Bool)]
 static extern bool SetForegroundWindow(IntPtr hWnd);

 //用來存放下面Form1.exe程序的物件
 private System.Diagnostics.Process formProc ;

 //假設有一支名為 Form1.exe 的視窗程式
 //先使用此方法執行(開啟)這支視窗程式
 public void Run()
 {
  //指定要開啟的檔案名稱
  System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("Form1.exe");

  //開啟檔案並回傳處理程序(之後需要此處理程序來取得Form1.exe的主視窗Handle值)
  formProc = System.Diagnostics.Process.Start(startInfo);
 }

 //切換至指定的視窗(利用此方法將Form1.exe的視窗帶到螢幕的最前面)
 public void Switch()
 {
  //切換視窗時需要該程序主視窗的Handle值(注意:是視窗的Handle不是程序的Handle)

  //第一步將該視窗設為作用中
  SetActiveWindow(formProc .MainWindowHandle);
  //第二步將該視窗帶到最前面
  SetForegroundWindow(formProc .MainWindowHandle);

  //完成!
 }
}

2009年2月5日 星期四

列出所有列舉內容

public enum ABC
{
 x = 1,
 y = 2,
 z = 3
}

//列出所有列舉內容
foreach (string str in Enum.GetNames(typeof(ABC)))
 System.Diagnostics.Debug.WriteLine(str);

//字串轉對應的列舉值
int i = (int)Enum.Parse(typeof(ABC) , "z");
System.Diagnostics.Debug.WriteLine(i.ToString());

2008年12月11日 星期四

控制項跨執行緒無效

//只要加上這一行,就能不檢查執行緒衝突
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

2008年10月16日 星期四

在Windows Service 讀不到 Register 的值

今天使用 Microsoft.Win32.Registry 類別
HKEY_CURRENT_USER\Software\下建立一個名稱為 "TMM" 的機碼
HKEY_CURRENT_USER\Software\TMM 下建立了一個,名稱為 "Path" 資料為 "C:\" 的字串值

當我在Windows Form 下做資料取回測試的時候,
string keyName = "HKEY_CURRENT_USER\Software\TMM";
string path = (string)Registry.GetValue(keyName, "Path", null);
一切都很正常

當我以同樣的方式把code加到我的 Windows Service後,卻怎麼樣也取不到值
看了http://topic.csdn.net/t/20040728/16/3219207.html此討論串之後
得知 Windows Service 讀取 HKEY_CURRENT_USER 下的資料是有些限制的

最後也因為怕麻煩,所以將原本寫在 HKEY_CURRENT_USER 的資料
全部改寫在 HKEY_LOCAL_MACHINE,問題就解決了。

2008年10月8日 星期三

C# 提供的Timer不準啦!

今天將Timer的Interval設為1000以下的時候發現被觸發的間隔時間並不是那麼準
Interval 設為 1 的時候 15ms 或 16ms 才會觸發一次
Interval 設為31的時候 31ms 或 32ms 才會觸發一次
Interval 設為32的時候 32ms、46ms 或 48ms 才會觸發一次
Interval 設為33的時候 45~48ms 才會觸發一次
這結果還滿怪的,不過看得出來有些規律性,每次約以15ms或16ms遞增。
ps. 搭配Stopwatch去看

看來只能直接使用win32的API了,不過高興的是在CodeProject有人將它包起來了。

http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx

2008年10月5日 星期日

C# 建立多參數的方法

有使用過 string.Format() 的都知道
在第一個參數之後可以接N個參數,如:
string.Format("{0}{1}{2}...{N}",v1,v2,...,vN);
這不可能用多載來建構N個方法吧
=.=

C# 中可利用 params 關鍵字來建立此方法

在使用上有幾點限制:
1. 在使用params之後不可以在有其他的參數
 void Test(string arg1, params object[ ] args, object count){...} //錯誤
 void Test(string arg1, params
object[ ] args){...} //正確
2. 一個方法中只能有一個 params 參數
 void Test(string arg1, params object[ ] args1, params object [] args2){...} //錯誤
3. 使用 params 的參數必須是一維陣列
 void Test(string arg1, params object arg){...} //錯誤

下面是一個將所有參數列出來的簡單例子:
public static void WriteAllParameters(params string[ ] list)
{
 for ( int i = 0 ; i <>
  Console.WriteLine( list[i] );
}

2008年9月28日 星期日

正則表達式

下面是自己嘗試寫出來的不保證一定正確
for C#

using
System.Text.RegularExpressions;

Regex 類別

[資料夾路徑驗證 ]
適用格式如下:
c: , c:\ , c:\abc
, c:\abc\

正則表達式如下:
"^[a-zA-Z]:(\\\\|(\\\\[^\\\\/:*?\"<>|]+)*|\\\\([^\\\\/:*?\"<>|]+\\\\)*)$"

[取得副檔名 ]
適用格式如下:
.a , .ab , .
abc , .abcd

正則表達式如下:
@"\.[a-zA-Z0-9]{1,4}$"

Match match = Regex.Match("要驗證的文字","正則表達式") ;
if (match.Success)
 string extName = match.Groups[0].Value;
else
 MessageBox.Show("無任何匹配");

[IPv4驗證 ]
適用格式如下:
0-255.0-255.0-255.0-255
ps. 開頭不得為0 ( ex. 192.168.00.001 )

正則表達式如下:
@"^(\d|[1-9]\d|1\d{1,2}|2[0-4]\d|25[0-5])(\.(\d|[1-9]\d|1\d{1,2}|2[0-4]\d|25[0-5])){3}$"

2008年9月23日 星期二

兩程式之間的訊息傳遞(使用SendMessage)

想要從一個程式傳送消息到另一個程式可以使用下面兩個Win32 API
1. SendMessage( ):用來傳遞消息代號
2. FindWindows( ):用來找出目標視窗的Handler

下面例子為由Client端發送訊息至Server端

Client端程式

using System.Runtime.InteropServices;

public class Client
{
 [DllImport("User32.dll", EntryPoint = "FindWindow")]
 private static extern int FindWindows(string lpClassName, string lpWindowName);

 [DllImport("User32.dll", EntryPoint = "SendMessage")]

 private static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
 
 
public Cliect()
 {
  //傳送代號為1982,且帶兩個參數為8與1的訊息到另一支程式
  SendMsgToServer(1982, 8, 1);    
 }

 //傳送訊息至Server端  
 public void SendMsgToServer(int msgCode, int wp, int lp)
 {
  //先取得另一支程式的視窗Handler,
  //這裡使用視窗標題名稱 "Form1" 來尋找
  int windowHandler = FindWindows(null, @"Form1");
  if (windowHandler > 0) 
  {
   //傳送訊息     
   int hr = SendMessage(windowHandler, msgCode, wp, lp);
  }
 }
}

Server端程式 (主要為覆寫 DefWndProc 事件處理函式)

publc class Server
{
 protected override void DefWndProc(ref Message m)
 {
  if (m.Msg == 1982)
  {
   MessageBox.Show(string.Format( "My birthday is {0}-{1}-{2}", m.Msg, m.WParam, m.LParam));
  }
  else
   base.DefWndProc(ref m);
 }
}

PS1. 如果電腦中同時有數個相同標題名稱的視窗,只有最上層的視窗收的到訊號,也就是說FindWindows( )只會回傳最上層視窗的Handler。

PS2.無法發送訊號時,請檢查msgCode是否太小。

2008年9月22日 星期一

Serialize(序列化) 與 Deserialize(還原序列化)

程式是在記憶體中執行的,一旦結束程式資料也就消失了
有時候我們希望將某個物件的內容(資料)保存起來
所以必須將資料寫進檔案中,要使用的時候再重新讀進來
至於寫入的格式該怎麼訂,讀出的時候該怎麼分析這就依照個人喜好了
有時候這些步驟是很麻煩的

現在有一個叫 IFormatter 的東西可以簡單的完成這項任務
下面的例子僅將物件讀進資料流,再由資料流寫回物件

假設我們有一個自定類別,定義如下:
[Serializable]
public class MyObject
{
  public int age = 0;
  public string name = string.empty;
}
//這裡需注意的是,要使該類別的物件能被序列化,該類別必須加入[Serializable]屬性

using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.IO;

public class Main
{
 public Main()
 {
 
 //處理序列化的物件
 
 IFormatter formatter = new BinaryFormatter();

 
 //要被序列化的物件
 
 MyObject obj = new MyObject();

 
 MemoryStream ms = new MemoryStream();
 
 //將物件序列化
  formatter .Serialize(ms, obj);

 
 //還原序列化資料
 
 ms.Position = 0;
 
 MyObject obj2 = (MyObject)formatter.Deserialize(ms);
 }
}

2008年7月27日 星期日

取得資料型態的大小(所佔的記憶體)

使用c的方式
unsafe
{
int size = sizeof( 資料型態名稱 );
}

使用c#的方式
int size = Marshal.SizeOf( 物件名稱 );
or
int size = Marshal.SizeOf( typeof( 資料型態名稱 ) );

資料型態可以是類別或結構

2008年7月10日 星期四

取得螢幕畫面

using System.Runtime.InteropServices;

[DllImport("user32.dll")]
private static extern int GetSystemMetrics(int index);


//取得螢幕解析度(w:寬 , h:高)
int w = GetSystemMetrics(0);
int h = GetSystemMetrics(1);
//建立畫布
Bitmap bmp = new Bitmap(w, h);
Graphics
gh = Graphics .FromImage(bmp);
//取得螢幕畫面( 畫面將填入bmp中)
gh.CopyFromScreen(0, 0, 0, 0, new Size(w,h), CopyPixelOperation.SourceCopy);

取得螢幕解析度

using System.Runtime.InteropServices;

[DllImport("user32.dll")]
private static extern int GetSystemMetrics(int index);


參數:
index : 0 表示取得寬度 , 1 表示取得高度