Kelp-Space 是記錄一些生活雜事的Blog
如有任何程式設計的問題歡迎到 飛特技術論壇 討論

2008-11-26

ListView 使用其他Column排序


執行結果就像這樣。
不使用第一排進行排序,而是使用第二或其他排來做排序。


在程式碼中加入以下class 複製程式碼(Copy to clipboard)
class ListViewItemComparer : System.Collections.IComparer
{
    private int col;
    public ListViewItemComparer()
    {
        col = 0;
    }
    public ListViewItemComparer(int column)
    {
        col = column;
    }
    public int Compare(object x, object y)
    {
        return String.Compare(((ListViewItem)x).SubItems[col].Text, ((ListViewItem)y).SubItems[col].Text);
    }
}

以下為範例程式 複製程式碼(Copy to clipboard)
private void button4_Click(object sender, EventArgs e)
{
    listView1.View = View.Details;
    listView1.Columns.Add("Column 1");
    listView1.Columns.Add("Column 2");
    listView1.Items.Add("Item0");
    listView1.Items.Add("Item1");
    listView1.Items.Add("Item2");
    listView1.Items[0].SubItems.Add("1");
    listView1.Items[1].SubItems.Add("0");
    listView1.Items[2].SubItems.Add("2");
    listView1.ListViewItemSorter = new ListViewItemComparer(1);     //使用Column 2進行排序
    listView1.Sort();
}

2008-10-25

如何學習程式設計

筆者從接觸程式到現在已經有五年了,這段期間碰過很多學習程式設計的人,大部分的人經過五年後還是差不多,但有一些人已經會做很危險的東西。功力的強弱不是看接觸多久,主要是看進步的速度,就像剛剛所說的,大部分的人花了五年的時間,卻達不到少數人一年所成長的功力。就科技產業而言,時間是很重要的,等到你龜速成長完畢後其他人不知道已經賺多少錢了,而且這些已經在賺錢的人不會成長嗎?很多人會問"學程式設計的秘訣是什麼?",其實筆者也不太清楚,如果硬要說的話天分是其中的一環。但光有天分是沒用的,這些成長速度很快的人一定有段時間是花大量時間在程式設計上,而成長速度很慢的人這時候通常在打電動,因為網路遊戲實在太令人著迷了。



第一代語言 - 機器語言
第二代語言 - 組合語言
第三代語言 - 程序導向語言 (ex:C語言)
第四代語言 - 物件導向語言 (ex:.NET)
第五代語言 - 問題導向語言或其他語言 (尚未普遍化)
最終語言 - 自然語言

目前這個世界已經進入第四代語言,物件導向語言。但在學術界還有很多老師停留在第三代語言。即使老師有跟上世界的腳步,教的是第四代語言,但是等到學生畢業後,主流語言還是第四代嗎?程式語言的最終目標就是自然語言,也就是要將程式簡單化,要讓開發時間縮短,目前軟體設計的難度跟以前比起來是簡單很多的。新一代語言一定有上一代語言的優點,如:撰寫容易、維護容易......等。這就是舊的語言一直在淘汰的原因,人們發現了更好用的語言後放棄了先前使用的語言。在學生階段,修了一堆語言,如:C、C++、JAVA、Basic......等,有很多人還會說"學了一堆語言,可是樣樣不精通",修了這麼多語言重點不是要你精通他,因為這些語言要成為吃飯工具的機會不高,學術界使用的語言很多都是過時的,學習這麼多語言的目的是要讓你學會"如何使用新的語言",這就是為什麼有人說"老師教的只有皮毛而已"。"這個語言我沒學過,所以沒辦法寫"大大們可能有聽過類似的話吧,如果學會如何使用新語言的人可能會說"這個語言我沒學過,可能要花一些時間",有些人使用新接觸的語言來設計簡單的木馬花不到兩星期就完成,筆者認為這才是真的"會寫程式"。


每種語言都有他的優缺點及限制,因此會有人說學某某語言才是對的,筆者認為學什麼語言都沒關係,因為你要做的事情不一定跟其他人一樣,而且對於會寫程式的人而言換語言的速度是很快的,所以慣用語言選擇能完成你想做的軟體即可,另外盡量挑選比較多人用的語言,這樣找資料會方便一點。


對於程式學習者來說,做一個自己想要的軟體是進步最快的方法,在做之前要謹慎的選擇適當的語言,這時候不要受限於學校教的語言。做3D遊戲的話盡量不要使用VB6,做木馬的話可以考慮VB6或delphi。


最近看到有人問說要學什麼語言所以才打這篇文章,希望本文能給想學程式設計的人一些解答,IT這條路是很累的......
迷:考試都快搞不定了還打文章

Sample Programs Using Asynchronous Sockets

Now that you have studied all the pieces, it’s time to put them together and create a set of real Windows asynchronous network programs. The following two programs recreate the SimpleTcpSrvr and SimpleTcpClient programs (Listings 5. 1 and 5.2, respectively) introduced in Chapter 5, "Connection-Oriented Sockets," but this time they use asynchronous network methods.

The Client Program
The AsyncTcpClient.cs program (Listing 8.2) uses the .NET Windows Forms library to create a Windows GUI environment for a simple TCP client. In a Windows environment, it is important that the program respond to Windows events from the user, as well as from the network


Listing 8.2: The AsyncTcpClient.cs program 複製程式碼(Copy to clipboard)
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
class AsyncTcpClient Form:
{
  private TextBox newText;
  private TextBox conStatus;
  private ListBox results;
  private Socket client;
  private byte[] data = new byte[1024];
  private int size = 1024;
  public AsyncTcpClient()
  {
   Text = "Asynchronous TCP Client";
   Size = new Size(400, 380);
   
   Label label1 = new Label();
   label1.Parent = this;
   label1.Text = "Enter text string:";
   label1.AutoSize = true;
   label1.Location = new Point(10, 30);
   newText = new TextBox();
   newText.Parent = this;
   newText.Size = new Size(200, 2 * Font.Height);
   newText.Location = new Point(10, 55);
   results = new ListBox();
   results.Parent = this;
   results.Location = new Point(10, 85);
   results.Size = new Size(360, 18 * Font.Height);
   Label label2 = new Label();
   label2.Parent = this;
   label2.Text = "Connection Status:";
   label2.AutoSize = true;
   label2.Location = new Point(10, 330);
   conStatus = new TextBox();
   conStatus.Parent = this;
   conStatus.Text = "Disconnected";
   conStatus.Size = new Size(200, 2 * Font.Height);
   conStatus.Location = new Point(110, 325);
   Button sendit = new Button();
   sendit.Parent = this;
   sendit.Text = "Send";
   sendit.Location = new Point(220,52);
   sendit.Size = new Size(5 * Font.Height, 2 * Font.Height);
   sendit.Click += new EventHandler(ButtonSendOnClick);
   Button connect = new Button();
   connect.Parent = this;
   connect.Text = "Connect";
   connect.Location = new Point(295, 20);
   connect.Size = new Size(6 * Font.Height, 2 * Font.Height);
   connect.Click += new EventHandler(ButtonConnectOnClick);
   Button discon = new Button();
   discon.Parent = this;
   discon.Text = "Disconnect";
   discon.Location = new Point(295,52);
   discon.Size = new Size(6 * Font.Height, 2 * Font.Height);
   discon.Click += new EventHandler(ButtonDisconOnClick);
  }
  void ButtonConnectOnClick(object obj, EventArgs ea)
  {
   conStatus.Text = "Connecting...";
   Socket newsock = new Socket(AddressFamily.InterNetwork,
              SocketType.Stream, ProtocolType.Tcp);
   IPEndPoint iep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
   newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
  }
  void ButtonSendOnClick(object obj, EventArgs ea)
  {
   byte[] message = Encoding.ASCII.GetBytes(newText.Text);
   newText.Clear();
   client.BeginSend(message, 0, message.Length, SocketFlags.None,
          new AsyncCallback(SendData), client);
  }
  void ButtonDisconOnClick(object obj, EventArgs ea)
  {
   client.Close();
   conStatus.Text = "Disconnected";
  }
  void Connected(IAsyncResult iar)
  {
   client = (Socket)iar.AsyncState;
   try
   {
     client.EndConnect(iar);
     conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString();
     client.BeginReceive(data, 0, size, SocketFlags.None,
            new AsyncCallback(ReceiveData), client);
   } catch (SocketException)
   {
     conStatus.Text = "Error connecting";
   }
  }
  void ReceiveData(IAsyncResult iar)
  {
   Socket remote = (Socket)iar.AsyncState;
   int recv = remote.EndReceive(iar);
   string stringData = Encoding.ASCII.GetString(data, 0, recv);
   results.Items.Add(stringData);
  }
  void SendData(IAsyncResult iar)
  {
   Socket remote = (Socket)iar.AsyncState;
   int sent = remote.EndSend(iar);
   remote.BeginReceive(data, 0, size, SocketFlags.None,
          new AsyncCallback(ReceiveData), remote);
  }
  public static void Main()
  {
   Application.Run(new AsyncTcpClient());
  }
}

The class constructor creates the window objects for the program. For this simple client program, the following objects are created:

A Label object and a TextBox object; these allow the customer to input text messages to send to the remote host

A ListBox object to display the messages returned by the remote host

A Label object and a TextBox object to display the connection status of the client program

Three Button objects; one for establishing a new TCP connection to a remote host, one for sending the text message and receiving a reply, and one for disconnecting the TCP session.

Each object is placed using the Point class and sized using the Size class; both of these classes are from the System.Drawing namespace. You can experiment with these values to get a feel for manually locating the objects on the Window form.

Note  If you have one of the Microsoft Visual products, such as Visual Studio or Visual C#, you can place all the Window objects using the graphical editing environment and allow the Form code to be generated automatically for you.


The Client Program Flow
You may notice that there is no network programming code at all in the class constructor. All of the network functions happen within EventHandler() methods. To get the AsyncTcpClient program to perform the same way as the original SimpleTcpClient program, you must first determine how to link the program protocol with the asynchronous events that will be triggered in the program. Then you must program them into the Windows event code methods. The diagram in Figure 8.3 shows each of the required methods and how they interact with the Windows event code. The following paragraphs describe the steps accomplished by the sample client program: connecting, receiving, sending, and disconnecting.



Connecting
As seen in the figure, when the customer clicks the Connect button, the method used to start the connection is performed. In the program code, this is the ButtonConnectOnClick() method:

ButtonConnectOnClick() 複製程式碼(Copy to clipboard)
void ButtonConnectOnClick(object obj, EventArgs ea)
{
  conStatus.Text = "Connecting...";
  Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
   ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
  newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
}

The ButtonConnectOnClick() method creates a new Socket object for the communication. Then it starts the BeginConnect() method with the address information of the remote host, the name of the associated AsyncCallback method, and the newly created Socket object. When this method finishes processing, Windows waits for the BeginConnect() method to trigger its event, which indicates that a connection is established with the remote host. When this occurs, program control is passed to the Connected() method:

Connected() 複製程式碼(Copy to clipboard)
void Connected(IAsyncResult iar)
{
  client = (Socket)iar.AsyncState;
  try
  {
   client.EndConnect(iar);
   conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString();
   client.BeginReceive(data, 0, size, SocketFlags.None,
    new AsyncCallback(ReceiveData), client);
  } catch (SocketException)
  {
   conStatus.Text = "Error connecting";
  }
}

The first thing that must be done in the Connected() method is to retrieve the original Socket object used for the connection. The AsyncState property of the IAsyncResult class returns the object passed to the AsyncCallback method, which in the case of the BeginConnect() method was the newly created Socket object.

After the Socket object is recreated, the EndConnect() method can be performed. Because it is possible that the EndConnect() method could fail (for instance, if the remote host is unavailable), it is a good idea to place it in a try-catch block. Should EndConnect() fail, you can notify the customer through the conStatus TextBox object.

In this program protocol, the first thing the server does after the connection is established is to send a welcome banner. To accommodate this, the AsyncTcpClient program must be prepared to accept an incoming message immediately after establishing the connection. This is done by using a BeginReceive() method call at the end of the Connected() method.

Receiving Data
After a new connection, and after every sent message, a ReceiveData() method is performed. The BeginReceive() method declares the ReceiveData() method, the AsyncCallback method that’s used when the data is received:

ReceiveData() 複製程式碼(Copy to clipboard)
void ReceiveData(IAsyncResult iar)
{
  Socket remote = (Socket)iar.AsyncState;
  int recv = remote.EndReceive(iar);
  string stringData = Encoding.ASCII.GetString(data, 0, recv);
  results.Items.Add(stringData);
}

Again, the first statement recreates the communication socket. After the original socket is recreated, the EndReceive() method is used, referencing the original IAsyncResult object, which pairs it with the original BeginReceive() method call. When the message is received from the remote host, it is placed in the data buffer referenced in the BeginReceive() method call. Because the data variable was defined as a global variable, it is used within this method to place the message in the results ListBox.

Sending Data
After entering a message in the TextBox object to send to the remote host, the customer clicks the Send button, and the SendData() method is performed. The EventHandler for the button points to the ButtonSendOnClick() method:

ButtonSendOnClick() 複製程式碼(Copy to clipboard)
void ButtonSendOnClick(object obj, EventArgs ea) { byte[] message = Encoding.ASCII.GetBytes(newText.Text); newText.Clear(); client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(SendData), client); }

The message is extracted from the TextBox object, converted to a byte array, and sent out the socket. Because the ButtonSendOnClick() method does not have the original Socket object passed to it, it needs to use a class member to reference the connected socket. The BeginSend() method is used on the connected socket. It specifies the message and the AsyncCallback method to call when the BeginSend() function is ready to complete, along with an object to pass to the EndSend() method. In this case, it is the connected socket.

The AsyncCallback method, SendData(), is triggered when the socket indicates it is ready to send the message:

SendData() 複製程式碼(Copy to clipboard)
void SendData(IAsyncResult iar)
{
  Socket remote = (Socket)iar.AsyncState;
  int sent = remote.EndSend(iar);
  remote.BeginReceive(data, 0, size, SocketFlags.None,
   new AsyncCallback(ReceiveData), remote);
}

Once again, you see the familiar behavior: the original connected socket is recreated using the AsyncState of the state object passed from the BeginSend() method. When the original socket is recreated, the EndSend() method completes the data transmission. The IAsyncResult object pairs the EndSend()to the original BeginSend() and EndSend()returns the number of bytes that were actually sent out from the socket.

In this application, after a message is sent, the server is expected to echo it back. Knowing this, the BeginReceive() method is called to start the receiving process. BeginReceive()again calls the same ReadData() method, just as it did to receive the original connection’s welcome banner.

Disconnecting
Now that you have the wonders of event programming at your disposal, you can finally create a button to control the disconnect from the remote host (rather than having to define a control word to stop the client). Here’s how that works:

ButtonDisconOnClick() 複製程式碼(Copy to clipboard)
void ButtonDisconOnClick(object obj, EventArgs ea)
{
  client.Close();
  conStatus.Text = "Disconnected";
}

By issuing the Close() method for the client socket, the connection is disconnected. To establish a new connection, the customer can click the Connect button.

Warning  There are lots of things that can go wrong with this simple client example, including the customer’s clicking the wrong button at the wrong time. A real-world production application should check each time a button is clicked to ensure that the function can be performed.

The Server Program

Now that you have moved the client program into the Windows world, it is time to tackle the server program. Listing 8.3 shows the AsyncTcpSrvr.cs program, which mimics the functionality of the SimpleTcpSrvr program (Listing 5.1) from Chapter 5 but uses a Windows Forms environment and asynchronous sockets.

Listing 8.3: The AsyncTcpSrvr.cs program 複製程式碼(Copy to clipboard)
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
class AsyncTcpSrvr    Form:
{
  private TextBox conStatus;
  private ListBox results;
  private byte[] data = new byte[1024];
  private int size = 1024;
  private Socket server;
  public AsyncTcpSrvr()
  {
   Text = "Asynchronous TCP Server";
   Size = new Size(400, 380);
   results = new ListBox();
   results.Parent = this;
   results.Location = new Point(10, 65);
   results.Size = new Size(350, 20 * Font.Height);
   Label label1 = new Label();
   label1.Parent = this;
   label1.Text = "Text received from client:";
   label1.AutoSize = true;
   label1.Location = new Point(10, 45);
   Label label2 = new Label();
   label2.Parent = this;
   label2.Text = "Connection Status:";
   label2.AutoSize = true;
   label2.Location = new Point(10, 330);
   conStatus = new TextBox();
   conStatus.Parent = this;
   conStatus.Text = "Waiting for client...";
   conStatus.Size = new Size(200, 2 * Font.Height);
   conStatus.Location = new Point(110, 325);
   Button stopServer = new Button();
   stopServer.Parent = this;
   stopServer.Text = "Stop Server";
   stopServer.Location = new Point(260,32);
   stopServer.Size = new Size(7 * Font.Height, 2 * Font.Height);
   stopServer.Click += new EventHandler(ButtonStopOnClick);
   server = new Socket(AddressFamily.InterNetwork,
          SocketType.Stream, ProtocolType.Tcp);
   IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
   server.Bind(iep);
   server.Listen(5);
   server.BeginAccept(new AsyncCallback(AcceptConn), server);
  }
  void ButtonStopOnClick(object obj, EventArgs ea)
  {
   Close();
  }
  void AcceptConn(IAsyncResult iar)
  {
   Socket oldserver = (Socket)iar.AsyncState;
   Socket client = oldserver.EndAccept(iar);
   conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString();
   string stringData = "Welcome to my server";
   byte[] message1 = Encoding.ASCII.GetBytes(stringData);
   client.BeginSend(message1, 0, message1.Length, SocketFlags.None,
         new AsyncCallback(SendData), client);
  }
  void SendData(IAsyncResult iar)
  {
   Socket client = (Socket)iar.AsyncState;
   int sent = client.EndSend(iar);
   client.BeginReceive(data, 0, size, SocketFlags.None,
         new AsyncCallback(ReceiveData), client);
  }
  void ReceiveData(IAsyncResult iar)
  {
   Socket client = (Socket)iar.AsyncState;
   int recv = client.EndReceive(iar);
   if (recv == 0)
   {
     client.Close();
     conStatus.Text = "Waiting for client...";
     server.BeginAccept(new AsyncCallback(AcceptConn), server);
     return;
   }
   string receivedData = Encoding.ASCII.GetString(data, 0, recv);
   results.Items.Add(receivedData);
   byte[] message2 = Encoding.ASCII.GetBytes(receivedData);
   client.BeginSend(message2, 0, message2.Length, SocketFlags.None,
          new AsyncCallback(SendData), client);
  }
  public static void Main()
  {
   Application.Run(new AsyncTcpSrvr());
  }
}

Just as the client program does, the AsyncTcpSrvr program uses basic Windows Forms objects to create the customer graphical environment:

A Label object and a ListBox object to identify the data received from the connected client

A Label object and a TextBox object to display the status of the socket and the connected client

A Button object to allow the customer to stop the server and exit the program

After creating the customer interface, you must code the network programming part. Unlike the client program, the AsyncTcpSrvr program includes network programming code that must be done in the class constructor.

The Server Program Flow

Like its counterpart SimpleTcpSrvr in Chapter 5, the AsyncTcpSrvr program must follow a set procedure for communicating with remote clients. Figure 8.5 diagrams the steps required for the server.


Waiting for New Client Connections
Because you know that the server must immediately listen for incoming connections, the required network programming code is added to the class constructor after the Forms objects have been created:

new Socket() 複製程式碼(Copy to clipboard)
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);
server.Bind(iep);
server.Listen(5);
server.BeginAccept(new AsyncCallback(AcceptConn), server);

By now, you should recognize this as standard server socket code: creating a new Socket object, binding it to a local IPEndPoint object, and listening for new connection attempts.

The BeginAccept() method specifies the AsyncCallback method to use when a connection is received, and the object to pass to the AsyncCallback method.

When a connection attempt is detected, the AsyncCallback method registered with the BeginAccept() method is performed:

AcceptConn() 複製程式碼(Copy to clipboard)
void AcceptConn(IAsyncResult iar)
{
  Socket oldserver = (Socket)iar.AsyncState;
  Socket client = oldserver.EndAccept(iar);
  conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString();
  string stringData = "Welcome to my server";
  byte[] message1 = Encoding.ASCII.GetBytes(stringData);
  client.BeginSend(message1, 0, message1.Length, SocketFlags.None,
   new AsyncCallback(SendData), client);
}

The AsyncCallback method recreates the original Socket object using the AsyncState property of the IAsyncResult object. When the EndAccept() method is called, it uses the IAsyncResult object to pair it up with the calling BeginAccept() method. The EndAccept() method returns a new Socket object to be used for all communication with the remote client.

As reflected in the program flow diagram, the next step for the server is to send a welcome banner to the client. This requires the BeginSend() method, which registers an AsyncCallback method to complete the send operation when the socket is ready to send out data.

Warning  Note that the Socket object passed to the AsyncCallback method is the newly created client socket, not the original server socket. This is the socket that is connected to the remote client, and it should be used for all communications with that client.

Sending Data
The EndSend() method is found in the AsyncCallback method registered in the BeginSend() method:

SendData() 複製程式碼(Copy to clipboard)
void SendData(IAsyncResult iar)
{
  Socket client = (Socket)iar.AsyncState;
  int sent = client.EndSend(iar);
  client.BeginReceive(data, 0, size, SocketFlags.None,
   new AsyncCallback(ReceiveData), client);
}

This sample program uses the standard EndSend() format. A good-quality production program would also compare this value with the original byte count of the sent message and perform the BeginSend() method again if some of the message were not properly sent.

The server program flow model specifies that after the welcome banner is sent, the server should wait for an incoming message from the client. This is accomplished with the BeginReceive() method, which specifies a data buffer in which to place the received data, along with the AsyncCallback method to call when the data is received.

Receiving Data
The EndReceive() method is placed in the AsyncCallback method for the BeginReceive() method:

ReceiveData() 複製程式碼(Copy to clipboard)
void ReceiveData(IAsyncResult iar)
{
  Socket client = (Socket)iar.AsyncState;
  int recv = client.EndReceive(iar);
  if (recv == 0)
  {
   client.Close();
   conStatus.Text = "Waiting for client...";
   server.BeginAccept(new AsyncCallback(AcceptConn), server);
   return;
  }
  string receivedData = Encoding.ASCII.GetString(data, 0, recv);
  results.Items.Add(receivedData);
  byte[] message2 = Encoding.ASCII.GetBytes(receivedData);
  client.BeginSend(message2, 0, message2.Length, SocketFlags.None, new AsyncCallback(SendData), client);
}

The ReceiveData() method is a little lengthier than the others because it has to accommodate two scenarios in the program flow. First, as always, the client socket is recreated using the standard AsyncState property. Next, the EndReceive() method is called using the IAsyncResult object to pair it up with the appropriate BeginReceive() method. EndReceive()returns the number of bytes received from the socket. As stated earlier, a real-time production program would check the number of bytes received against an expected message size.

If the received message size is zero bytes, it is assumed that the remote client has disconnected the TCP session. In that case, the client socket is closed, and the server can start listening for a new client connection by using the BeginAccept() method and starting the whole program flow all over again.

If a message has been received from the remote client, it must be displayed in the ListBox object and echoed back to the client. This is done by using the BeginSend() method again. Because the program flow now duplicates the original flow from sending the welcome banner, the original SendData() method is used for this AsyncCallback method as well.

取自C# Network Programing

霹靂燈 - 使用右移減少燈數

某天在看加強版遊戲王的時候MSN突然傳來求救訊息。
順道把這個功能的程式PO上來。
這個功能怎麼想都只能想到這麼爛的標題。
直接看功能要求。
使用晶片為8051。


功能要求 複製程式碼(Copy to clipboard)
●●●●●●●
●●●●●●○
●●●●●○●
●●●●●○○
●●●●○●○
●●●●○○●
●●●●○○○
●●●○●○○
●●●○○●○
●●●○○○●
●●●○○○○
●●○●○○○
●●○○●○○
●●○○○●○
●●○○○○●
●●○○○○○
●○●○○○○
●○○●○○○
●○○○●○○
●○○○○●○
●○○○○○●
●○○○○○○
○●○○○○○


程式碼 複製程式碼(Copy to clipboard)
#include <REGX51.H>

void delay(void)
{
        unsigned long m;
        for(m=0;m<2000;m++);
}

int main(void)
{
        int i,j,x;
        while(1)
        {
                i=0xff;
                j=1;
                P2=i;
                delay();

                while(i>0)      //第一層迴圈   用來減少霹靂燈數量
                {
                        i<<=1;
                        j<<=1;
                        x=j;     //設定右移霹靂燈起始位置
                        while(x>1)     //第二層迴圈 用來右移霹靂燈
                        {
                                x>>=1;
                                P2=i|x;
                                delay();
                        }
                        P2=i;
                        delay();
                }
        }
}

Ark - Data Backuper 緩備份軟體 (開源碼 1.0.0.4)

【軟體名稱】:Ark - Data Backuper
【軟體分類】:檔案備份
【軟體性質】:開源軟體
【檔案大小】:566kB
【放置空間】:Phate
【軟體介紹】:
/// ///////////////////////////////////
/// 專案名稱:Ark - Data Backuper
///
/// 開始日期:2008-09-01
/// 結束日期:2008-10-12
///
/// 開發者:
/// Kelp[at]phate.tw (Kelp @ Phate Technology)
///
/// 開發語言:
/// Visual C# 2008
///
/// 用途:
/// 主要提供緩備份功能
///
///
/// 記錄:
/// 2008-10-12
/// 1.0.0 版完成
/// 1.0.0.1 修正每日一次時間 更改為24小時制
///
/// 2008-10-13
/// 1.0.0.2 檔案容量不同時不可進行覆蓋,只有最後修改時間較新時才能覆蓋
/// 1.0.0.2 啟動後記錄先前視窗大小
/// 1.0.0.3 Standby時消除狀態bar
///
/// 2008-10-14
/// 1.0.0.4 對開機讀不到資料的部分進行修正
/// 1.0.0.4 系統開啟程式時自動隱藏視窗
///
/// ///////////////////////////////////





此軟體使用少量的系統資源進行檔案複製,能夠把A資料底下的所有檔案夾拷貝到B資料夾中。
使用者可以選擇固定的時間進行備份。
其實是在下硬碟太多顆了,整理起來真的不是一般的糟糕 (誤。
硬碟裡的程式每天都會改一些,所以備份已經做到很煩了,就用這隻軟體來方便方便吧。 XD
開源是為了讓程式進步得更快,如有任何BUG可以通知我們,或自行修改程式碼(修改後希望能通知我們)。
我們也歡迎開發亞種Ark。

執行檔載點
程式碼載點

抓取檔案的ICON

抓取檔案的ICON程式碼 複製程式碼(Copy to clipboard)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace TestProject
{
    public partial class Form1 : Form
    {
        [System.Runtime.InteropServices.DllImport("shell32")]
        private static extern IntPtr ExtractAssociatedIcon(IntPtr hInst, string lpIconPath, ref int lpiIcon);
        private IntPtr hIcon;

        public Form1()
        {
            InitializeComponent();

            this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);

            int iIconIndex = 0;
            hIcon = ExtractAssociatedIcon(this.Handle, "D:\\123.jpg", ref iIconIndex);
        }

        private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Icon icon = Icon.FromHandle(hIcon);
            e.Graphics.DrawIcon(icon, 10, 10);
        }
    }
}

抓取短檔名

C#是使用unicode所以遇到日文或其他語言的路徑都不太會發生問題。
但使用了.net framework以外的東西,傳了其他語言的路徑時有可能出錯。

筆者而在.net framework裡沒找到轉shortPath的函數,所以只好調用API....
如果.net framework可以直接轉的話就請大大PO上來了。


抓取短檔名 複製程式碼(Copy to clipboard)
using System.Runtime.InteropServices;   //調用API

        //在class內
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern int GetShortPathName([MarshalAs(UnmanagedType.LPTStr)] string path, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath, int shortPathLength);

        //在事件內程式碼
        StringBuilder shortPath = new StringBuilder(255);
        GetShortPathName("C:\test測試.txt", shortPath, shortPath.Capacity);

進制轉換簡介

//十進制轉二進制
Console.WriteLine(Convert.ToString(69, 2));
//十進制轉八進制
Console.WriteLine(Convert.ToString(69, 8));
//十進制轉十六進制
Console.WriteLine(Convert.ToString(69, 16));

//二進制轉十進制
Console.WriteLine(Convert.ToInt32(”100111101″, 2));
//八進制轉十進制
Console.WriteLine(Convert.ToInt32(”76″, 8));
//十六進制轉十進制
Console.WriteLine(Convert.ToInt32(”FF”, 16));

2008-09-12

2008、2009年作品預告

2008年12月中前預計完成Ark - Data Backuper 1.1
2009年12月初前預計完成Evis Ain 1.3
2009年12月底前預計完成Evis Vita 1.3

Ark是用來緩備份的軟體,軟體性質為開源碼。
Evis Ain 為遠控軟體,軟體性質為免費軟體。
Evis Vita 為遠控軟體,軟體性質為付費軟體。

2008-09-06

GetDevice.ocx 抓取電腦硬體名稱

GetDevice.ocx這個元件可以用來抓取電腦硬體名稱。
像是RS232、USB......等
尤其是RS232,一般用到RS232的軟體都有一個combox讓使用者選擇要用哪個port。
而要列出這些port讓使用者選擇時總不能連不存在的port也列上去。
先用這個元件把RS232硬體抓出來後再將這些port加入combox是一個不錯的方法。
檔案下載位置 (VB6程式碼)

2008-09-03

Ark Data Backuper 開發記錄

Ark Data Backuper是一款用來緩備份的軟體。
算是一種常駐軟體,當他在備份時不會消耗過高的CPU及硬碟使用率。
本專案從9/1開始策劃,軟體性質為開源碼。

2008-08-25

FC 1.0 開發記錄

今天最後測試完成。
速度也調上來了,一開始速度被拖下來是程式上的缺失,C#的速度跟VB6差不多。
優點是真正的多執行緒,因此很容易的將掃描報告傳回來。
VB要做的話一定要寫成兩隻exe,不然只要開始測試就會看到程式死在那邊。
因為VB沒有真正的多執行緒,我記得之前寫的時候第二個執行緒的程式連物件都不能用。
要傳掃描報告回主控端的話有三個方法。
1. 記憶體共用。 -- 這個真的超複雜的
2. 事件中夾帶參數傳遞。 -- 程式不好寫
3. 寫到硬碟。 -- 這個速度會慢一點點 重點是感覺好鳥 = =|||

C#的話輕鬆過關,叫第二個執行緒出來就好。

2008-08-18

使用Socket完成FTP檔案存取

為了使用.net framework 2.0完成FTP檔案傳輸,真是花了不少時間。
這隻程式用了Barakbbn.Freeware.Net.Sockets。
使用時總共要加入兩個.cs檔(Barakbbn.Freeware.Net.SocketsKelp.Opensource.FTPClient)。
相關說明有打在註解上,如果還是不清楚的話可以留言發問。
Barakbbn.Freeware.Net.Sockets相關文章

Kelp.Opensource.FTPClient 複製程式碼(Copy to clipboard)

using System;
using System.Net;
using System.IO;
using System.Text;
using Barakbbn.Freeware.Net.Sockets;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  本程式需要使用額外的socket Barakbbn.Freeware.Net.Sockets
//
//  在程式碼上方加入 using Kelp.Opensource.FTPClient;
//
//
//  P.S.下達ftp.Gep()後不會等抓完檔案才執行ftp.DisConnect()
//      檔案上傳及下載是透過事件觸發的
//      "//檔案下載完成"搜尋此字串可以找到下載完成程式位置  事件為GetFileComplete
//      "//檔案上傳完成"搜尋此字串可以找到上傳完成程式位置  事件為PutFileComplete
//
//
//  FTPClient ftp = new FTPClient();    //宣告
//
//  void Connect()                               //連線
//  void DisConnect()                            //關閉連線
//  void SetTransferType(TransferType ttType)    //設定傳輸模式
//  TransferType GetTransferType()               //取得傳輸模式
//  string[] Dir(string strMask)                 //取得文件列表  (文件名稱~可用*)
//  void Delete(string strFileName)              //刪除
//  void Rename(string strOldFileName, string strNewFileName)    //Rename(如果要改的名稱已存在將會覆蓋)
//  void Get(string strRemoteFileName, string strLocalFileName)  //下載文件
//  void Put(string strFileName)                 //上傳文件
//  void MkDir(string strDirName)                //建立目錄
//  void RmDir(string strDirName)                //刪除目錄
//  void ChDir(string strDirName)                //改變目錄
//
//  來源:打奈特(.net)
//  修改:Kelp
//
//  修改記錄
//      2008/08/16
//          因為要使用.net framework2.0來完成FTP傳輸因此到處尋找利用socket進行FTP的程式碼
//
//      2008/08/18
//          原程式因為不斷掃描socket的緩衝區造成錯誤
//          將System.Net.Socket換成Barakbbn.Freeware.Net.Sockets
//
//      2008/08/19
//          修正不穩定因素
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  下載範例程式
    string[] sdata;
  
    FTPClient ftp = new FTPClient();    宣告
    ftp.GetFileComplete += new EventHandler<LocalGFileAddressData>(ftp_GetFileComplete);
    ftp.RemoteHost = "www.test.com";    設定HOST
    ftp.RemoteUser = "XXXXX";           設定使用者帳號
    ftp.RemotePass = "XXXXX";           設定密碼
    ftp.Connect();                      連線
    ftp.ChDir("/www/");                 切換目錄
    sdata = ftp.Dir("");                取得目前位置內的資料夾及檔案名稱
    ftp.Get("1.jpg", "D:\\1.jpg");      下載1.jpg另存為F:\\1.jpg
    ftp.DisConnect();                   結束連線
   
    private void ftp_GetFileComplete(object sender, LocalGFileAddressData e)
    {
        MessageBox.Show("Finish " + e.LocalFileAddress);
    }
*/
/*  上傳範例程式
    string[] sdata;

    FTPClient ftp = new FTPClient();
    ftp.PutFileComplete += new EventHandler<LocalPFileAddressData>(ftp_PutFileComplete);
    ftp.RemoteHost = "www.test.com";    設定HOST
    ftp.RemoteUser = "XXXXX";           設定使用者帳號
    ftp.RemotePass = "XXXXX";           設定密碼
    ftp.Connect();                      連線
    ftp.Put("F:\\2.jpg");               上傳檔案
       
    private void ftp_PutFileComplete(object sender, LocalPFileAddressData e)
    {
        MessageBox.Show("Finish " + e.LocalFileAddress);
    }
*/

namespace Kelp.Opensource.FTPClient
{
    public class FTPClient
    {
        //////////////////////////記憶體宣告/////////////////////////////////////////////////////////////////////////////
        #region Field

        private bool Received = false;      //當基礎連接socket回應結束後為true
        private bool DataReceived = false;  //當資料連接socket回應結束後為true
        private string strMsg;              //伺服器回應的訊息
        private string strReply;            //伺服器回應的答應碼
        private int iReplyCode;             //伺服器回應的答應碼
        private TcpClient socketControl;    //socket物件
        private TransferType trType;        //傳輸模式
        byte[] buffer = new byte[0];

        Encoding ASCII = Encoding.GetEncoding("big5");  //編碼方式
        public enum TransferType { Binary, ASCII };     //傳輸模式

        bool Downloading = false;
        bool Uploading = false;
        string SOutputAddress = "";         //檔案下載路徑
        FileStream output;                  //檔案下載串流
        string SInputAddress = "";          //檔案上傳路徑
        FileStream input;                   //檔案上傳串流
        int iBytes = 0;                     //檔案上傳指標

        TcpClient socketGetData;
        TcpClient socketSendData;
        #endregion
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////Client/////////////////////////////////////////////////////////////////////////////////
        #region FTPClient
        public FTPClient()
        {
            strRemoteHost = "";
            strRemotePath = "";
            strRemoteUser = "";
            strRemotePass = "";
            strRemotePort = 21;
            bConnected = false;
        }

        public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort)
        {
            strRemoteHost = remoteHost;
            strRemotePath = remotePath;
            strRemoteUser = remoteUser;
            strRemotePass = remotePass;
            strRemotePort = remotePort;
            Connect();
        }
        #endregion
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////屬性更改對應程式///////////////////////////////////////////////////////////////////////
        #region Loging Property
        private string strRemoteHost;
        public string RemoteHost
        {
            get
            {
                return strRemoteHost;
            }
            set
            {
                strRemoteHost = value;
            }
        }

        private int strRemotePort;
        public int RemotePort
        {
            get
            {
                return strRemotePort;
            }
            set
            {
                strRemotePort = value;
            }
        }

        private string strRemotePath;
        public string RemotePath
        {
            get
            {
                return strRemotePath;
            }
            set
            {
                strRemotePath = value;
            }
        }

        private string strRemoteUser;
        public string RemoteUser
        {
            set
            {
                strRemoteUser = value;
            }
        }

        private string strRemotePass;
        public string RemotePass
        {
            set
            {
                strRemotePass = value;
            }
        }

        private Boolean bConnected;
        public bool Connected
        {
            get
            {
                return bConnected;
            }
        }
        #endregion
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////事件///////////////////////////////////////////////////////////////////////////////////
        public virtual event EventHandler<LocalGFileAddressData> GetFileComplete;
        public virtual event EventHandler<LocalPFileAddressData> PutFileComplete;
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////Class函數//////////////////////////////////////////////////////////////////////////////
        public void Connect()                               //連線
        {
            socketControl = new TcpClient();
            socketControl.Key = "Bace";     //設定Key為基礎連接socket
            WireTcpClient(socketControl);   //設定socket對應事件

            try
            {
                Received = false;
                socketControl.Connect(RemoteHost, Convert.ToInt32(strRemotePort));
            }
            catch (Exception)
            {
                throw new IOException("Couldn't connect to remote server");
            }
            // 取得回應
            while (!Received) ;
            if (iReplyCode != 220)
            {
                DisConnect();
                throw new IOException(strReply.Substring(4));
            }
            // 登入
            SendCommand("USER " + strRemoteUser);
            if (!(iReplyCode == 331 || iReplyCode == 230))
            {
                CloseSocketConnect();//如果有錯誤就關閉連線
                throw new IOException(strReply.Substring(4));
            }
            if (iReplyCode != 230)
            {
                SendCommand("PASS " + strRemotePass);
                if (!(iReplyCode == 230 || iReplyCode == 202))
                {
                    CloseSocketConnect();
                    throw new IOException(strReply.Substring(4));
                }
            }
            bConnected = true;
            // 切換到所選的目錄
            ChDir(strRemotePath);
        }

        public void DisConnect()                            //關閉連線
        {
            if (socketControl != null)
            {
                SendCommand("QUIT");
            }
            if (socketSendData != null)
                socketSendData.Close();
            if (socketSendData != null)
                socketSendData.Close();
            CloseSocketConnect();
        }

        public void SetTransferType(TransferType ttType)    //設定傳輸模式
        {
            if (ttType == TransferType.Binary)
            {
                SendCommand("TYPE I");//binary
            }
            else
            {
                SendCommand("TYPE A");//ASCII
            }
            if (iReplyCode != 200)
            {
                throw new IOException(strReply.Substring(4));
            }
            else
            {
                trType = ttType;
            }
        }

        public TransferType GetTransferType()               //取得傳輸模式
        {
            return trType;
        }

        public string[] Dir(string strMask)                 //取得文件列表  (文件名稱~可用*)
        {
            if (!bConnected)    // 先確定是否已連線
                Connect();

            DataReceived = false;
            TcpClient socketData = CreateDataSocket();  //建立並行數據連接的socket
            socketData.Key = "Data";
            SendCommand("NLST " + strMask);             //傳送指令
            //分析回應碼
            if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))
            {
                throw new IOException(strReply.Substring(4));
            }
            //取得結果
            while (!DataReceived) ;     //等待傳輸結束
            while (true)
            {
                int iBytes = socketData.Receive(buffer, 0, buffer.Length);
                if (iBytes < 0)
                    break;
                strMsg += ASCII.GetString(buffer, 0, iBytes);
            }
            char[] seperator = { '\n' };
            string[] strsFileList = strMsg.Split(seperator);
            for (int ILoop = 0; ILoop < strsFileList.GetUpperBound(0); ILoop++)
            {
                strsFileList[ILoop] = strsFileList[ILoop].TrimEnd();
            }

            socketData.Close();
            return strsFileList;
        }

        public void Delete(string strFileName)              //刪除
        {
            if (!bConnected)
                Connect();
            SendCommand("DELE " + strFileName);
            if (iReplyCode != 250)
            {
                throw new IOException(strReply.Substring(4));
            }
        }

        public void Rename(string strOldFileName, string strNewFileName)    //Rename(如果要改的名稱已存在將會覆蓋)
        {
            if (!bConnected)
            {
                Connect();
            }
            SendCommand("RNFR " + strOldFileName);
            if (iReplyCode != 350)
            {
                throw new IOException(strReply.Substring(4));
            }

            SendCommand("RNTO " + strNewFileName);
            if (iReplyCode != 250)
            {
                throw new IOException(strReply.Substring(4));
            }
        }

        public void Get(string strRemoteFileName, string strLocalFileName)  //下載文件
        {
            if (!bConnected)
                Connect();
            SetTransferType(TransferType.Binary);
            if (strLocalFileName.Equals(""))
            {
                strLocalFileName = strRemoteFileName;
            }
            if (!File.Exists(strLocalFileName))
            {
                Stream st = File.Create(strLocalFileName);
                st.Close();
            }
            SOutputAddress = strLocalFileName;
            Downloading = true;
            socketGetData = CreateDataSocket();
            socketGetData.Key = "GetFile";

            output = new FileStream(SOutputAddress, FileMode.Append);
            SendCommand("RETR " + strRemoteFileName);
            if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226 || iReplyCode == 250))
            {
                throw new IOException(strReply.Substring(4));
            }
        }

        public void Put(string strFileName)                 //上傳文件
        {
            if (!bConnected)
                Connect();
            socketSendData = CreateDataSocket();
            socketSendData.Key = "SendFile";
            SendCommand("STOR " + Path.GetFileName(strFileName));
            if (!(iReplyCode == 125 || iReplyCode == 150))
            {
                throw new IOException(strReply.Substring(4));
            }
            SInputAddress = strFileName;
            Uploading = true;
            input = new FileStream(strFileName, FileMode.Open);

            iBytes = input.Read(buffer, 0, buffer.Length);
            socketSendData.Send(buffer, 0, iBytes);
        }

        public void MkDir(string strDirName)                //建立目錄
        {
            if (!bConnected)
            {
                Connect();
            }
            SendCommand("MKD " + strDirName);
            if (iReplyCode != 257)
            {
                throw new IOException(strReply.Substring(4));
            }
        }

        public void RmDir(string strDirName)                //刪除目錄
        {
            if (!bConnected)
            {
                Connect();
            }
            SendCommand("RMD " + strDirName);
            if (iReplyCode != 250)
            {
                throw new IOException(strReply.Substring(4));
            }
        }

        public void ChDir(string strDirName)                //改變目錄
        {
            if (strDirName.Equals(".") || strDirName.Equals(""))
            {
                return;
            }
            if (!bConnected)
            {
                Connect();
            }
            SendCommand("CWD " + strDirName);
            if (iReplyCode != 250)
            {
                throw new IOException(strReply.Substring(4));
            }
            this.strRemotePath = strDirName;
        }
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////內部函數///////////////////////////////////////////////////////////////////////////////
        private TcpClient CreateDataSocket()        //建立並行數據連接的Socket
        {
            SendCommand("PASV");
            if (iReplyCode != 227)
            {
                throw new IOException(strReply.Substring(4));
            }
            int index1 = strReply.IndexOf('(');
            int index2 = strReply.IndexOf(')');
            string ipData = strReply.Substring(index1 + 1, index2 - index1 - 1);
            int[] parts = new int[6];
            int len = ipData.Length;
            int partCount = 0;
            string buf = "";
            for (int i = 0; i < len && partCount <= 6; i++)
            {
                char ch = Char.Parse(ipData.Substring(i, 1));
                if (Char.IsDigit(ch))
                    buf += ch;
                else if (ch != ',')
                {
                    throw new IOException("Malformed PASV strReply: " + strReply);
                }
                if (ch == ',' || i + 1 == len)
                {
                    try
                    {
                        parts[partCount++] = Int32.Parse(buf);
                        buf = "";
                    }
                    catch (Exception)
                    {
                        throw new IOException("Malformed PASV strReply: " + strReply);
                    }
                }
            }
            string ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3];
            int port = (parts[4] << 8) + parts[5];
            TcpClient s = new TcpClient();
            WireTcpClient(s);
            IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress), port);
            try
            {
                s.Connect(ep);
            }
            catch (Exception)
            {
                throw new IOException("Can't connect to remote server");
            }
            return s;
        }

        private void CloseSocketConnect()           //關閉Socket的連線(用在登入以前)
        {
            if (socketControl != null)
            {
                socketControl.Close();
                socketControl = null;
            }
            bConnected = false;
        }

        private void SendCommand(String strCommand) //傳送命令並取得回應碼和最後一行的回應字串
        {
            Encoding e = Encoding.GetEncoding("big5");
            Byte[] cmdBytes = e.GetBytes((strCommand + "\r\n").ToCharArray());
            Received = false;
            socketControl.Send(cmdBytes, 0, cmdBytes.Length);
            if (strCommand != "QUIT")
                while (!Received) ;
        }

        void WireTcpClient(TcpClient tcpClient)     //建立Socket事件
        {
            tcpClient.Error += new EventHandler<SocketErrorEventArgs>(socket_Error);
            tcpClient.SendCompleted += new EventHandler(socket_SendCompleted);
            tcpClient.Disconnected += new EventHandler<SocketDisconnectedEventArgs>(socket_Disconnected);
            tcpClient.DataAvailable += new EventHandler(socket_DataAvailable);
            tcpClient.DataArrived += new EventHandler<SocketDataArrivedEventArgs>(socket_DataArrived);
            tcpClient.Connected += new EventHandler(socket_Connected);
            tcpClient.DataLost += new EventHandler<SocketDataArrivedEventArgs>(socket_DataLost);
            tcpClient.SendProgressChanged += new EventHandler<SocketDataSendProgressChangedEventArgs>(socket_SendProgressChanged);
        }
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////Socket事件/////////////////////////////////////////////////////////////////////////////
        void socket_DataLost(object sender, SocketDataArrivedEventArgs e)
        {

        }
        void socket_DataArrived(object sender, SocketDataArrivedEventArgs e)
        {
            TcpClient Socket = sender as TcpClient;
            int iBytes;

            switch (Socket.Key)
            {
                case "Bace":
                    try
                    {
                        buffer = (byte[])ReDim(buffer, e.ReceivedSize);
                        iBytes = socketControl.Receive(buffer, 0, buffer.Length);
                        strReply = ASCII.GetString(buffer, 0, iBytes);
                        iReplyCode = Int32.Parse(strReply.Substring(0, 3));
                    }
                    catch
                    {
                        break;
                    }

                    if (iReplyCode == 226)
                    {
                        if (Downloading)
                        {
                            //檔案下載完成
                            Downloading = false;
                            output.Close();
                            LocalGFileAddressData g = new LocalGFileAddressData(SOutputAddress);
                            GetFileComplete(socketGetData, g);
                        }
                        else if (Uploading)
                        {
                            //檔案上傳完成
                            Uploading = false;
                            input.Close();
                            LocalPFileAddressData h = new LocalPFileAddressData(SInputAddress);
                            PutFileComplete(socketSendData, h);
                        }
                    }
                   
                    Received = true;
                    break;
                case "Data":
                    DataReceived = true;
                    break;
                case "GetFile":
                    while (true)
                    {
                        iBytes = Socket.Receive(buffer, 0, buffer.Length);
                        if (iBytes < 0)
                        {
                            break;
                        }
                        output.Write(buffer, 0, iBytes);
                    }
                    break;
            }
        }
        void socket_Connected(object sender, EventArgs e)
        {

        }
        void socket_DataAvailable(object sender, EventArgs e)
        {
           
        }
        void socket_Disconnected(object sender, SocketDisconnectedEventArgs e)
        {
            TcpClient Socket = sender as TcpClient;
            switch (Socket.Key)
            {
                case "GetFile":
                    if (Socket.IsConnected)
                    {
                        Received = false;
                        Socket.Close();
                    }
                    break;
            }
        }
        void socket_SendCompleted(object sender, EventArgs e)
        {
            TcpClient Socket = sender as TcpClient;
            switch (Socket.Key)
            {
                case "SendFile":
                    iBytes = input.Read(buffer, 0, buffer.Length);
                    if (iBytes > 0)
                        Socket.Send(buffer, 0, iBytes);
                    else
                    {
                        if (Socket.IsConnected)
                        {
                            Received = false;
                            Socket.Close();
                        }
                    }
                    break;
            }
        }
        void socket_Error(object sender, SocketErrorEventArgs e)
        {

        }
        void socket_SendProgressChanged(object sender, SocketDataSendProgressChangedEventArgs e)
        {

        }
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //////////////////////////通用副程式區域/////////////////////////////////////////////////////////////////////////
        public static Array ReDim(Array origArray, Int32 desiredSize)   //重新宣告記憶體
        {
            Type t = origArray.GetType().GetElementType();
            Array newArray = Array.CreateInstance(t, desiredSize);
            Array.Copy(origArray, 0, newArray, 0, Math.Min(origArray.Length, desiredSize));
            return newArray;
        }
        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    }
    public class LocalGFileAddressData : EventArgs
    {
        private string sLocalFileAddress;

        public LocalGFileAddressData(string sLocalFileAddress)
        {
            this.sLocalFileAddress = sLocalFileAddress;
        }
        public string LocalFileAddress
        {
            get { return this.sLocalFileAddress; }
        }
    }
    public class LocalPFileAddressData : EventArgs
    {
        private string sLocalFileAddress;

        public LocalPFileAddressData(string sLocalFileAddress)
        {
            this.sLocalFileAddress = sLocalFileAddress;
        }
        public string LocalFileAddress
        {
            get { return this.sLocalFileAddress; }
        }
    }
}