用C#設計Windows應用程序模板

來源: 中國IT實驗室  發布時間: 2009-10-23 14:45  閱讀: 2722 次  推薦: 0   [收藏]  

 通常windows應用程序都有相似的特征:控件、菜單、工具條、狀態欄等等。每次我們開始作一個新的windows應用程序時都是以相同的事情開始:建立項目,添加控件和事件處理器。如果我們有一個模板,那么我們就可以節約大量的時間了。

  在介紹如何建立模板的過程中,將涉及大量的微軟.net framework類庫的基本知識。如果你沒有使用集成開發環境那么本文介紹的模板對你將非常有用,如果你使用了visual studio.net這樣的集成開發環境你也可以從中了解控件的工作方式,這對你也是很有用的。

  寫一個windows應用程序總是從下面的幾個步驟開始:
  1、創建一個窗體
  2、給窗體添加控件
  3、添加菜單和菜單項,并綁定到窗體上
  4、創建工具條
  5、添加狀態欄
  6、添加事件處理器

  在windows應用程序開發中,你不可能完全跳過這些步驟,你可以對他作些修改,但不可能完全跳過。

  創建窗體

  在.Net FrameWork程序設計中,窗體總是System.Windows.Forms.Form類的子類,他繼承聊著各類的全部特征,你甚至不用添加任何一行代碼就可以創建window窗體了。現在我們創建一個form類的子類myapp,需要注意的是在說明繼承時使用冒號:

using System.Windows.Forms;
public class MyWinApp: Form 
{
}

  與其他程序相似,我們需要一個main()的主方法作為應用程序的入口。在main()中使用System.Windows.Forms的run方法來開始應用程序和顯示窗體。run方法有三種重載方式,對于windows應用程序,我們采取重載一個窗體對象的方式:

public static void Main()
{
     MyWinApp form = new MyWinApp();
     Application.Run(form);
}

  作為選擇,可以在main()方法中將兩行代碼寫成一行:

public static void Main() 
{
    Application.Run(new MyWinApp());
}

  設置屬性

  一旦有了窗體,就可以設置它的屬性(象高度、寬度、標題等)并指定一個象圖1那樣的圖標,可以通過代碼或從構造器重調用一個方法來完成這個設置。在list1中有一個方法InitializeComponent,可以將初始化代碼寫入其中。

  使用width和height屬性設置寬度和高度

this.Width = 400;
this.Height = 300; 

  使用窗體的text屬性設置標題

this.Text = "My Windows Application"; 

  設置圖標

  如果未作說明,windows應用程序將顯示一個缺省圖標,可以修改這個圖標,方法是設置窗體的icon屬性,這個屬性接受一個System.Drawing.Icon對象。Icon類有幾個可以用于初始化Icon對象的構造函數,需要說明的是最好提供.ico文件的完全路徑。

this.Icon = new Icon(imageFolder + "applicationLogo.ico"); 

  這里 imageFolder是一個靜態域,用于指示icon文件的目錄,imageFolder的定義如下:

static String imageFolder = "Images" +Path.DirectorySeparatorChar.ToString(); 

  這告訴應用程序icon文件在應用程序的image目錄下,這里使用了System.IO.Path 類的DirectorySeparatorChar屬性獲得操作系統用于分隔目錄和父目錄的分隔符,在這里沒有使用"/",這是因為對于windows操作系統這是正確的,但對于linux和unix則不然。這也是為了證明模板對于其他操作系統也是方便的。

  窗體的位置

  使窗體居中時非常有用的,要達到這個目的,需要使用StartPosition屬性,并將FormStartPosition 的一個成員賦給他。

this.StartPosition = FormStartPosition.CenterScreen; 

  當然也可以用form類的CenterToScreen方法是窗體居中,但這個方法不能直接使用。

this.CenterToScreen(); 

  form類還有其他一些讓人感興趣的屬性和方法,這里列出了其中的部分:

  1、設置Opacity 屬性創建一個透明或半透明的窗體
  2、設置modal屬性使窗體為模式的或非模式的
  3、通過BackColor屬性改變窗體的背景顏色
  4、將TopMost屬性設置為true,以確定窗體在其他所有非最頂部窗體之上

  給窗體添加控件

  windows控件均繼承自System.Windows.Forms.Control類,control類處理用戶輸入、安全等,他給窗體的控件提供了一個windows句柄,以及一些重要的屬性,如Name, Enabled, Text, BackColor, Left, Top, Size, Location, Visible, Width, 和 Height。

  System.Windows.Forms名稱空間提供了12個控件,每一個控件都有它自己的屬性和特征,所以在篇文章中我們不可能全部討論。給窗體添加控減非常容易,下面的代碼給窗體添加了三個控件,分別是:Label, Button, 和TreeView。

Label label;
Button button;
TreeView tree;  

  為了簡便,可以在聲明的同時實例化這些對象。

Label label = new Label();
Button button = new Button();
TreeView tree = new TreeView(); 

  然后在InitializeComponent方法中設置這些控件的屬性,尤其是設置控件的大小和在窗體中的位置,對于大小可以使用width和height屬性,比如treeview控件的大小可以使用下面的屬性:

tree.Width = 100;
tree.Height = 100;  

  確定控件的位置可以使用控件的left和top屬性,這兩個屬性決定了控件的左上角的位置,就像下面的語句決定了treeview的位置:

tree.Top = 40;
tree.Left = 20;  

  當然你也可以使用更簡單的Location屬性,將System.Drawing.Point結構的實例賦給他。我們用這種方法確定Label和Button的位置。

label.Location = new Point(220, 40);
button.Location = new Point(220, 80); 

  下一步就是要使控件在窗體上可見。使用Form.ControlCollection類的add方法將每個控件添加到窗體的ControlCollection中,ControlCollection可以使用窗體的控件屬性訪問。

this.Controls.Add(label);
this.Controls.Add(button);
this.Controls.Add(tree);

  添加菜單和菜單項

  要找到沒有菜單的windows應用程序非常困難,菜單使訪問應用程序的功能變得很簡單,在大多數環境下可以最小的使用控件。菜單比控件占用更少的空間,同時使應用程序顯得更有組織。

在System.Windows.Forms名稱空間中,所有與菜單相關的控件都是menu類的子類。menu是一個抽象類,你不能直接實例化,menu類有三個子類:

ContextMenu
MainMenu
MenuItem 

  ContextMenu類表示快捷菜單,在控件或窗體區域點擊鼠標右鍵時顯示。快捷菜單常用于組合窗體mainmenu類的菜單項給出應用程序的上下文,這對于用戶時非常有用的。

  MainMenu表示傳統的位于窗體頂部的菜單,你可以把它看成窗體菜單結構的容器。一個菜單是由MenuItem表示的菜單項組成的,對于應用程序而言每一個菜單項是一個命令或其它子菜單項的父菜單。form類都有一個menu屬性,采用將mainmenu對象賦給menu屬性的方式將mainmenu對象綁定到窗體。

  在這個模板中,我們沒有使用ContextMenu類,但我們示范了如何使用MainMenu和MenuItem類。我們首先需要在窗體中添加一個菜單,給窗體添加一個MainMenu對象。

MainMenu mainMenu = new MainMenu(); 

  現在MainMenu對象中什么都沒有,下面我們給他添加一個MenuItem對象。在List1中主菜單稱為fileMenuItem,它的text屬性是&File,&表示他后面的字母帶下劃線,是該菜單的快捷鍵。通過使用Menu對象的MenuItemCollection的add方法為MainMenu添加一個或幾個MenuItem,這個集合可以通過menu類的MenuItems屬性訪問。

MenuItem fileMenuItem = new MenuItem();
mainMenu.MenuItems.Add(fileMenuItem); 

  我們在fileMenuItem 菜單項中還添加了其它MenuItem,這些MenuItem是fileMenuItem的子菜單。你也可以給子菜單添加子菜單。圖2顯示了菜單的等級結構。

---------圖2---------

  菜單項的聲明如下:

MenuItem fileNewMenuItem;
MenuItem fileOpenMenuItem;
MenuItem fileSaveMenuItem;
MenuItem fileSaveAsMenuItem;
MenuItem fileMenuWithSubmenu;
MenuItem submenuMenuItem;
MenuItem fileExitMenuItem;

  MenuItem類有幾個構造函數,使用這些構造函數實例化你的 MenuItem對象,并添加一個事件處理器。

// the following constructor is the same as:
// menuItem fileNewMenuItem = new MenuItem();
// fileNewMenuItem.Text = "&New";
// fileNewMenuItem.Shortcut = Shortcut.CtrlN;
// fileNewMenuItem.Click += new
// System.EventHandler(this.fileNewMenuItem_Click);
fileNewMenuItem = new MenuItem("&New",
new System.EventHandler(this.fileNewMenuItem_Click),
Shortcut.CtrlN);fileOpenMenuItem = new MenuItem("&Open",
new System.EventHandler(this.fileOpenMenuItem_Click), Shortcut.CtrlO);

fileSaveMenuItem = new MenuItem("&Save",
new System.EventHandler(this.fileSaveMenuItem_Click), 
Shortcut.CtrlS);fileSaveAsMenuItem = new MenuItem("Save &As",
new System.EventHandler(this.fileSaveAsMenuItem_Click));

fileMenuWithSubmenu = new MenuItem("&With Submenu");

submenuMenuItem = new MenuItem("Su&bmenu",
new System.EventHandler(this.submenuMenuItem_Click));

fileExitMenuItem = new MenuItem("E&xit",
new System.EventHandler(this.fileExitMenuItem_Click));

Event handling is discussed further in the section "Adding Event Handlers."As mentioned, 
the menu items are added to the fileMenuItem control.fileMenuItem
  .MenuItems.Add(fileNewMenuItem);

fileMenuItem.MenuItems.Add(fileOpenMenuItem);

fileMenuItem.MenuItems.Add(fileSaveMenuItem);
fileMenuItem.MenuItems.Add(fileSaveAsMenuItem);
fileMenuItem.MenuItems.Add(fileMenuWithSubmenu);
fileMenuWithSubmenu.MenuItems.Add(submenuMenuItem);
fileMenuItem.MenuItems.Add("-");
// add a separatorfileMenuItem.MenuItems.Add(fileExitMenuItem); 

  注意在菜單項之間可以創建一個分隔符,方法是使用menu類的MenuItems集合的add方法。上面的例子中使用的分隔符是"-"。

  創建工具條

  為了使應用程序的界面更友好,可以在窗體中添加一個工具條。工具條由System.Windows.Forms.ToolBar類描述。窗體中可有多個工具條,工具條中包含了一個或多個ToolBarButton類描述的按鈕,可以在每個按鈕中插入圖像或圖標,要達到這個目的你需要一個ImageList控件作為圖像容器。

ImageList imageList = new ImageList(); 

  對于每個圖像文件首先要實例化為image對象,然后將這些圖像添加到ImageList控件中,Image和Bitmap類可以在System.Drawing名稱空間中找到。

Image newFileImage = new Bitmap(imageFolder + "newFile.bmp");
Image openFileImage = new Bitmap(imageFolder + "openFile.gif");
Image saveFileImage = new Bitmap(imageFolder + "saveFile.bmp");
Image printImage = new Bitmap(imageFolder + "print.gif");
...
imageList.Images.Add(newFileImage);
imageList.Images.Add(openFileImage);
imageList.Images.Add(saveFileImage);
imageList.Images.Add(printImage);

  注意你可以使用Images集合的add方法將image對象加入到imagelist控件中。現在為將這些圖加入到控件中,必須將ImageList控件賦給ToolBar的ImageList屬性。

toolBar.ImageList = imageList; 

  然后將ImageList控件中的圖像賦給工具按鈕的ImageIndex屬性。

newToolBarButton.ImageIndex = 0;
openToolBarButton.ImageIndex = 1;
aveToolBarButton.ImageIndex = 2;
printToolBarButton.ImageIndex = 3; 

  象菜單項一樣,現在必須把工具按鈕加入到工具條中。

toolBar.Buttons.Add(separatorToolBarButton);
toolBar.Buttons.Add(newToolBarButton);
toolBar.Buttons.Add(openToolBarButton);
toolBar.Buttons.Add(saveToolBarButton);
toolBar.Buttons.Add(separatorToolBarButton);
toolBar.Buttons.Add(printToolBarButton); 

  最后將工具條加入到窗體中。

this.Controls.Add(toolBar); 

  添加狀態條

  狀態條由System.Windows.Forms.StatusBar描述,它提供了定制控件的外觀的屬性,狀態條由StatusBarPanel對象組成,在我們的模板中狀態條有兩個嵌套板:

StatusBar statusBar = new StatusBar();
StatusBarPanel statusBarPanel1 = new StatusBarPanel();
StatusBarPanel statusBarPanel2 = new StatusBarPanel();

  狀態條和狀態條上的嵌套板由下面的代碼設置:

statusBarPanel1.BorderStyle = StatusBarPanelBorderStyle.Sunken;
statusBarPanel1.Text = "Press F1 for Help";
statusBarPanel1.AutoSize = StatusBarPanelAutoSize.Spring;
statusBarPanel2.BorderStyle = StatusBarPanelBorderStyle.Raised;
statusBarPanel2.ToolTipText = System.DateTime.Now.ToShortTimeString();
statusBarPanel2.Text = System.DateTime.Today.ToLongDateString();
statusBarPanel2.AutoSize = StatusBarPanelAutoSize.Contents;
statusBar.ShowPanels = true;statusBar.Panels.Add(statusBarPanel1);
statusBar.Panels.Add(statusBarPanel2); 

  同樣我們需要將狀態條添加到窗體中:

this.Controls.Add(statusBar); 

  事件處理器

  在windows程序設計中添加事件處理器是最重要的任務。事件處理器保證了程序與用戶交互,同時完成其他重要的功能。在c#中你可以給控件和菜單事件添加事件處理器以俘獲你想處理的事件,下面的代碼給Button控件的click事件設計了一個事件處理器:

button.Click += new System.EventHandler(this.button_Click); 

  button_Click事件處理器必須被處理:

private void button_Click(Object sender, System.EventArgs e) 
{
    MessageBox.Show("Thank you.", "The Event Information");
}

  MenuItem 對象在實例化的同時可以給賦以一個事件處理器:

fileNewMenuItem = new MenuItem("&New",
new System.EventHandler(this.fileNewMenuItem_Click), Shortcut.CtrlN);

fileOpenMenuItem = new MenuItem("&Open",
new System.EventHandler(this.fileOpenMenuItem_Click), Shortcut.CtrlO);

fileSaveMenuItem = new MenuItem("&Save",
new System.EventHandler(this.fileSaveMenuItem_Click), Shortcut.CtrlS);

fileSaveAsMenuItem = new MenuItem("Save &As",
new System.EventHandler(this.fileSaveAsMenuItem_Click));

fileMenuWithSubmenu = new MenuItem("&With Submenu");

submenuMenuItem = new MenuItem("Su&bmenu",
new System.EventHandler(this.submenuMenuItem_Click));

fileExitMenuItem = new MenuItem("E&xit",
new System.EventHandler(this.fileExitMenuItem_Click)); 

  你不能給工具按鈕指派一個事件處理器,但可以給工具條指派一個事件處理器:

toolBar.ButtonClick += newToolBarButtonClickEventHandler(this.toolBar_ButtonClick);
protected void toolBar_ButtonClick(Object sender, ToolBarButtonClickEventArgse) 
    {
        // Evaluate the Button property to determine which button was clicked.
        switch (toolBar.Buttons.IndexOf(e.Button)) 
            {
            case 1:MessageBox.Show("Second button.", "The Event Information");
            break;
            case 2:MessageBox.Show("third button", "The Event Information");
            break;
            case 3:MessageBox.Show("fourth button.", "The Event Information");
            break;
            }
    }

  例子中也給窗體的close事件設計了一個事件處理器,通過重載OnClosing方法你可以接收用戶點擊窗體的X按鈕,這樣你可以取消關閉事件:

protected override void OnClosing(CancelEventArgs e)
 {
    MessageBox.Show("Exit now.", "The Event Information");
}

  現在我們的模板就完成了,你可以使用他開始你的WINDOWS應用程序設計。

  附錄 Listing 1. C# Windows 應用程序模板

/*
to compile this source file, typecsc MyWinApp.cs
*/
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using System.ComponentModel;
public class MyWinApp: Form
{
    Label label = new Label();
    Button button = new Button();
    TreeView tree = new TreeView();
    ImageList imageList = new ImageList();
    static String imageFolder = "Images" +Path.DirectorySeparatorChar.ToString();
    // -------------- Images declarations 
    Image newFileImage = new Bitmap(imageFolder + "newFile.bmp");
    Image openFileImage = new Bitmap(imageFolder + "openFile.gif");
    Image saveFileImage = new Bitmap(imageFolder + "saveFile.bmp");
    Image printImage = new Bitmap(imageFolder + "print.gif");
    // -------------- End of Images declaration

    // -------------- menu ------------------
    MainMenu mainMenu = new MainMenu();
    MenuItem fileMenuItem = new MenuItem();
    MenuItem fileNewMenuItem;
    MenuItem fileOpenMenuItem;
    MenuItem fileSaveMenuItem;
    MenuItem fileSaveAsMenuItem;
    MenuItem fileMenuWithSubmenu;
    MenuItem submenuMenuItem;
    MenuItem fileExitMenuItem;
    // -------------- End of menu --------------
    // -------------- Toolbar 
    ToolBar toolBar = new ToolBar();
    ToolBarButton separatorToolBarButton = new ToolBarButton();
    ToolBarButton newToolBarButton = new ToolBarButton();
    ToolBarButton openToolBarButton = new ToolBarButton();
    ToolBarButton saveToolBarButton = new ToolBarButton();
    ToolBarButton printToolBarButton = new ToolBarButton();
    // -- End of Toolbar 
    // ----- StatusBar -----------
    StatusBar statusBar = new StatusBar();
    StatusBarPanel statusBarPanel1 = new StatusBarPanel();
    StatusBarPanel statusBarPanel2 = new StatusBarPanel();
    // -------------- End of StatusBar ----
        public MyWinApp() 
        {
        InitializeComponent();
        }
    
    private void InitializeComponent() 
    {
        this.Text = "My Windows Application";
        this.Icon = new Icon(imageFolder + "applicationLogo.ico");
        this.Width = 400;this.Height = 300;
        this.StartPosition = FormStartPosition.CenterScreen;
        imageList.Images.Add(newFileImage);
        imageList.Images.Add(openFileImage);
        imageList.Images.Add(saveFileImage);
        imageList.Images.Add(printImage);
        // menufileMenuItem.Text = "&File";
        // the following constructor is the same as:
        // menuItem fileNewMenuItem = new MenuItem();
        // fileNewMenuItem.Text = "&New";
        // fileNewMenuItem.Shortcut = Shortcut.CtrlN;
        // fileNewMenuItem.Click += new

        System.EventHandler(this.fileNewMenuItem_Click);
        fileNewMenuItem = new MenuItem("&New",
        new System.EventHandler(this.fileNewMenuItem_Click), Shortcut.CtrlN);

        fileOpenMenuItem = new MenuItem("&Open",
        new System.EventHandler(this.fileOpenMenuItem_Click), Shortcut.CtrlO);

        fileSaveMenuItem = new MenuItem("&Save",
        new System.EventHandler(this.fileSaveMenuItem_Click), Shortcut.CtrlS);

        fileSaveAsMenuItem = new MenuItem("Save &As",
        new System.EventHandler(this.fileSaveAsMenuItem_Click));

        fileMenuWithSubmenu = new MenuItem("&With Submenu");

        submenuMenuItem = new MenuItem("Su&bmenu",
        new System.EventHandler(this.submenuMenuItem_Click));

        fileExitMenuItem = new MenuItem("E&xit",
        new System.EventHandler(this.fileExitMenuItem_Click));

        mainMenu.MenuItems.Add(fileMenuItem);
        fileOpenMenuItem.Checked = true;
        fileMenuItem.MenuItems.Add(fileNewMenuItem);
        fileMenuItem.MenuItems.Add(fileOpenMenuItem);
        fileMenuItem.MenuItems.Add(fileSaveMenuItem);
        fileMenuItem.MenuItems.Add(fileSaveAsMenuItem);
        fileMenuItem.MenuItems.Add(fileMenuWithSubmenu);
        fileMenuWithSubmenu.MenuItems.Add(submenuMenuItem);
        fileMenuItem.MenuItems.Add("-"); // add a separator

        fileMenuItem.MenuItems.Add(fileExitMenuItem);
        toolBar.Appearance = ToolBarAppearance.Normal;
        //toolBar.Appearance = ToolBarAppearance.Flat;
        toolBar.ImageList = imageList;
        toolBar.ButtonSize = new Size(14, 6);

        separatorToolBarButton.Style = ToolBarButtonStyle.Separator;
        newToolBarButton.ToolTipText = "New Document";
        newToolBarButton.ImageIndex = 0;
        openToolBarButton.ToolTipText = "Open Document";
        openToolBarButton.ImageIndex = 1;
        saveToolBarButton.ToolTipText = "Save";
        saveToolBarButton.ImageIndex = 2;
        printToolBarButton.ToolTipText = "Print";
        printToolBarButton.ImageIndex = 3;

        toolBar.ButtonClick += new 
        ToolBarButtonClickEventHandler(this.toolBar_ButtonClick);

        toolBar.Buttons.Add(separatorToolBarButton);
        toolBar.Buttons.Add(newToolBarButton);
        toolBar.Buttons.Add(openToolBarButton);
        toolBar.Buttons.Add(saveToolBarButton);
        toolBar.Buttons.Add(separatorToolBarButton);
        toolBar.Buttons.Add(printToolBarButton);

        tree.Top = 40;
        tree.Left = 20;
        tree.Width = 100;
        tree.Height = 100;

        label.Location = new Point(220, 40);
        label.Size = new Size(160, 30);label.Text = "Yes, click the button";
        button.Location = new Point(220, 80);
        button.Size = new Size(100, 30);
        button.Text = "Click this";
        button.Click += new System.EventHandler(this.button_Click);

        statusBarPanel1.BorderStyle = StatusBarPanelBorderStyle.Sunken;
        statusBarPanel1.Text = "Press F1 for Help";
        statusBarPanel1.AutoSize = StatusBarPanelAutoSize.Spring;
        statusBarPanel2.BorderStyle = StatusBarPanelBorderStyle.Raised;
        statusBarPanel2.ToolTipText = System.DateTime.Now.ToShortTimeString();
        statusBarPanel2.Text = System.DateTime.Today.ToLongDateString();
        statusBarPanel2.AutoSize = StatusBarPanelAutoSize.Contents;
        statusBar.ShowPanels = true;statusBar.Panels.Add(statusBarPanel1);
        statusBar.Panels.Add(statusBarPanel2);
        this.Menu = mainMenu;this.Controls.Add(toolBar);
        this.Controls.Add(tree);this.Controls.Add(label);
        this.Controls.Add(button);
        this.Controls.Add(statusBar);
    }

        // -------------- Event Handlers 
    private void fileNewMenuItem_Click(Object sender, EventArgs e) 
    {
        MessageBox.Show("You clicked the File -- New menu.", "The Event Information");
    }

    private void fileOpenMenuItem_Click(Object sender, EventArgs e) 
    {
        MessageBox.Show("You clicked the File -- Open menu.", "The Event Information");
    }

    private void fileSaveMenuItem_Click(Object sender, EventArgs e) 
    {
        MessageBox.Show("You clicked the File -- Save menu.", "The Event Information");
    }

        private void fileSaveAsMenuItem_Click(Object sender, EventArgs e)
    {
        MessageBox.Show("You clicked the File -- Save As menu.", "The Event Information");
    }

    private void fileExitMenuItem_Click(Object sender, EventArgs e)
    {
        MessageBox.Show("You clicked the File -- Exit As menu.", "The Event Information");
    }

    private void submenuMenuItem_Click(Object sender, EventArgs e)
    {
        MessageBox.Show("You clicked the submenu.", "The Event Information");
    }
    protected void toolBar_ButtonClick(Object sender,ToolBarButtonClickEventArgs e) 
    {
        // Evaluate the Button property to determine which button was clicked.
        switch (toolBar.Buttons.IndexOf(e.Button)) 
        {
            case 1:MessageBox.Show("Second button.", "The Event Information");
            break;

            case 2:MessageBox.Show("third button", "The Event Information");
            break;

            case 3:MessageBox.Show("fourth button.", "The Event Information");
            break;
        }
    }

    protected override void OnClosing(CancelEventArgs e) 
    {
        MessageBox.Show("Exit now.", "The Event Information");
    }

    private void button_Click(Object sender, System.EventArgs e) 
    {
        MessageBox.Show("Thank you.", "The Event Information");
    }

    // -------------- End of Event Handlers 

    public static void Main() 
    {
        MyWinApp form = new MyWinApp();
        Application.Run(form);
    }

}
0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()