2015年9月1日 星期二

C# WPF程式->如何將Canvas物件存成圖片

這個問題看似很簡單,但實際在網路找尋相關資源來實作都會碰到相同問題。

就是: 為何輸出的圖片與Canvas圖層上的畫面不同,那以下程式碼是解法!!!


步驟流程如下:
1. 將canvas做 UIElement Updata
2. 使用RenderTargetBitmap 將canvas物件存成bitmap物件
3. 使用FileStream存成指定格式的圖片。



//-------以下是圖片匯出

            //--設定圖片繪製方法
            ImageBrush Mybrush = new ImageBrush();
            //--將該.png 做成底圖
            Mybrush.ImageSource = new BitmapImage(new Uri(@"C:\CWB\EEW07.png", UriKind.Relative));
            //--繪製到canvas物件作為背景
            canvas.Background = Mybrush;

            //--以下對canvas物件做 UIElement更新
            Size tSize = new Size(canvas.Width, canvas.Height);
            //--更新canvas物件
            canvas.Measure(tSize);
            //--更新後的物件傳遞
            canvas.Arrange(new Rect(new Point(0, 0), tSize));

            //接著將圖像做保存
            //設定一個DrawingVisual 存放canvas的繪製結果
            DrawingVisual tDrawingVisual = new DrawingVisual();
            using (DrawingContext context = tDrawingVisual.RenderOpen())
            {
                //存放canvas
                VisualBrush tVisualBrush = new VisualBrush(canvas);
                //將像素塗滿
                tVisualBrush.Stretch = Stretch.Fill;
                //塗滿範圍為 0~ 880寬 與 0 ~ 600高
                context.DrawRectangle(tVisualBrush, null, new Rect(0, 0, 880, 600));
                context.Close();
            }

            //轉成BitMap的存放容器
            RenderTargetBitmap tRenderTargetBitmap = new RenderTargetBitmap((int)canvas.RenderSize.Width, (int)canvas.RenderSize.Height, 96d, 96d, PixelFormats.Default);
            //將我們剛剛繪製好的tDrawingVisual轉成bitmap物件
            tRenderTargetBitmap.Render(tDrawingVisual);

            //準備存進去
            using (FileStream tFileStream = new FileStream("C:\\Taiwan.png", FileMode.Create, FileAccess.Write))
            {
                //-我要存成Png格式 所以用PngBitmapEncoder
                PngBitmapEncoder tPngBitmapEncoder = new PngBitmapEncoder();
                //-然後啟用點陣圖交錯格式
                tPngBitmapEncoder.Interlace = PngInterlaceOption.On;
                //-將tRenderTargetBitmap轉成PNG
                tPngBitmapEncoder.Frames.Add(BitmapFrame.Create(tRenderTargetBitmap));
                //存到C:\\Taiwan.png 檔案中
                tPngBitmapEncoder.Save(tFileStream);
                //關閉
                tFileStream.Close();
            }

2015年8月24日 星期一

使用Javascript 將 主網頁資訊傳遞給 自身iframe內嵌網頁資料 iframe傳值的方法

網頁A (A.html):

 <iframe onload="setName('123')" name="history_page" id="history_page" src="B.html" width="240" height="130" scrolling="no" frameborder="0"></iframe>


function setName(str) {
       
        history_page.document.History_form.str_name.value = str;
    }


網頁B(B.html):


 <!--從主頁取得123值 -->
    <form action="abc.cgi" name="History_form" id="History_form" method="post">
        <input type="hidden" name="str_name" id="str_name" value="">
    </form>




從網頁A載入的時候就會一併將值透過iframe 的onload事件 將值傳遞個B.html 中的 str_name資料。 

2015年8月10日 星期一

記憶卡片遊戲-周星馳電影主題

剛上研究所時自修程式,閒暇之餘寫出來的小品遊戲。說明如下:


開啟程式MEMORY CARY.exe 檔案,會有兩個選擇
1.點擊左邊周星馳的臉進入遊戲
2.點擊右邊周星馳的臉離開遊戲


















進入遊戲後左下角會有開始跟離開的按鈕
遊戲難度為中間讀秒的地方有分10秒、15秒、20秒

















按下開始後會先倒數3秒看所有牌面的位置,然後會翻面。玩家找出位置即可。

遊戲下載位置: 點我下載

2015年8月7日 星期五

C# 發送Google E-Mail Sample Code

以下介紹C# 的郵件服務功能 ,該範例使用Visual Studio 2013  Windows Form 撰寫

需要參考引用 using System.Net.Mail;
比較要注意的地方是:
1.  寄件者SMTP : google的位址為 smtp.gmail.com  如果要使用其他郵件服務需要修改
2.  寄件者Port : 同上,google需要開啟587 Port 
3.  寄件者Gmail帳號: 要輸入自己的google gmail帳號
4.  寄件者密碼:要輸入自己的google gmail密碼


程式畫面圖:

當按下寄郵件按鈕,如果成功:










以下是程式碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Mail;//---使用郵件參考功能
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GoogleGmail
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 發送郵件的按鈕
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            string Catcher = textBox_Catcher.Text;//-收件者 會自動幫我們,分隔
            string Title = textBox_Title.Text;//-----信件標題
            string Body = textBox_Body.Text;//-------信件內容
           
            string SenderName= textBox_Name.Text;//寄件者姓名
            string Sender= textBox_SenderMail.Text;//寄件者
            string UserName=textBox_UserName.Text;//寄件者帳號 這裡以Gmail做設定
            string PassWord=textBox_Password.Text;//寄件者密碼
            int Port =int.Parse(textBox_Port.Text);//Port號 GoogleGmail是587
            string SMTP = textBox_SMTP.Text;//-------SMTP 這裡以Gmail的伺服器為範例



            MailMessage msg = new MailMessage();//-----------------建立mail object
            msg.To.Add(Catcher);//收件者,自動以逗號分隔不同收件者

            //信件的寄件者郵件地址, 姓名 ,使用的編碼
            msg.From = new MailAddress(Sender, SenderName, System.Text.Encoding.UTF8);

            msg.Subject = Title;//郵件標題
            msg.SubjectEncoding = System.Text.Encoding.UTF8;//郵件標題編碼
            msg.Body = Body;//郵件內容
            msg.BodyEncoding = System.Text.Encoding.UTF8;//郵件內容編碼
            msg.IsBodyHtml = false;//是否是HTML郵件
            msg.Priority = MailPriority.Normal;//郵件優先級

            try
            {
                //建立 SmtpClient 物件 並設定 Gmail的smtp主機及Port
                SmtpClient MySmtp = new SmtpClient(SMTP, Port);

                //設定你的帳號密碼
                MySmtp.Credentials = new System.Net.NetworkCredential(UserName, PassWord);

                //Gmial 的 smtp 使用 SSL
                MySmtp.EnableSsl = true;

                //發送Email
                MySmtp.Send(msg);

                MessageBox.Show("發送成功!!!");
            }
            catch (System.Net.Mail.SmtpException ex)
            {
                MessageBox.Show("發送失敗:"+ex.Message);
            }

        }

        }
    }



程式Sample Code 原始碼 下載位置: 點我下載
程式執行檔案   下載位置: 點我下載



2015年7月23日 星期四

ClickOnce發行的奇怪錯誤," 無法發行 因為無法建置專案 ",另類解法

2015/07/23 使用tortoisesvn後,取得的最新版本程式當要發行時會出現 " 無法發行 因為無法建置專案"

1.如下圖,當我發行時 使用滑鼠右鍵(對專案) -> 屬性 後指向到發行位置



2. 會出現以下的問題@@?




3. 後來嘗試使用滑鼠右鍵(點擊專案) -> 發行(B)... 就可以使用發行精靈正常發行了。

推測是屬性的發行在經過版本控制軟體後已經有造成錯誤了,只能用重新設定發行的方式進行發行。


2015年7月22日 星期三

TortoiseSVN 如何從遠端的檔案庫取得資料

1.先確認遠端位置的檔案位置

在遠端的: 192.168.8.100 位置
檔案路徑為: file:///E:/CWB/CWBProgramFile
 

2.
因此我們只要把檔案庫URL: 的地方E:/  改成 192.168.8.100\ 即可
取出目錄就是將檔案存放的位置。

2015年6月22日 星期一

C# 安裝windows服務 與 移除服務的方法

1.當寫完windows服務後會有以下畫面:
  該服務擁有一個WatchDogForDisasterResouce.exe 檔案 該檔案必須使用installutil.exe 進行安裝,要使用該元件就需要使用命令提示字元進行安裝( 一個方法 )

2. 這個installutil.exe 元件 預設在 C:\\Windows\\Microsoft.Net\\Framework\\v4.0.30319\\
資料夾底下

3. 接著我們開啟命令提示字元 
   C:\Windows\Microsof.Net\Framework\v4.0.30310\InstallUtil.exe 
表示使用的安裝元件位置 接著空一格 加入以下(服務的.exe位置):
  C:\Users\Administrator\Desktop\DisasterResource\WatchDogForDisasterResource\bin\Debug\WacthDogForDisasterResource.exe

按下鍵盤上的Enter就可以安裝完成!


4. 如果需要移除服務請輸入以下:   
   sc delete disasterresourceservicecatchapi
 
   ※也就是 sc delete (服務名稱)  

5. 步驟4的disasterresourceservicecatchapi其實也就是如下圖服務的福稱

2015年6月20日 星期六

C# WinForm 使用log4net 紀錄log的方法 - >最快速成使用

1. 先到log4net網站下載最新版的log4net
    http://logging.apache.org/log4net/download_log4net.cgi



















2. 接著請選擇 log4net-1.2.13-bin-newkey.zip 當前最新版本下載


3.接著將下載來的壓縮檔案進行解壓縮
















4.在資料夾中 log4net-1.2.13-bin-newkey//og4net-1.2.13//bin//net-cp//3.5//release 資料夾底下的log4net.dll 就是我們C# winform程式所需要參考的檔案

5. 請先建立一個visual 2008 以上版本的 C# winfrom專案 ,畫面應該會是如下

6.我們在建立的專案底下 建立"Resouce"資料夾,並且將剛剛的log4net.dll 語 log4net.xml 複製到"Resouce"資料夾中 (也就是我們建立的專案底下建立一個"Resource"資料夾並將檔案放入)

7.接著回到C#專案-> 方案總管視窗 -> 參考 ->滑鼠右鍵 ->加入參考(剛剛Resouce底下的log4net.dll )  成功應該會如下:

8. 然後我們在主程式的地方加入
    using log4net;
    using log4net.Appender;


9. 接著在專案中建立一個資料夾 "Lib" 目的是為了加入應用程式組態,如下面兩張圖的步驟



10.打開app.config 加入以下的log4net資訊

<?xml version="1.0"?>
<configuration>
    <configSections>
       <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net-net-1.0" />
    </configSections>

  <log4net>
     <root>
     <level value="ALL"/>
     <appender-ref ref="LogFileAppender"/>
     <appender-ref ref="UdpAppender"/>
    </root>

   <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
              <param name="File" value="MyLog.txt"/>
              <param name="AppendToFile" value="MyLog.txt"/>
              <layout type="log4net.Layout.PatternLayout">
                    <param name="ConversionPattern" value="%d %-5level 第%L行 &gt;%n - %m%n"/>
              </layout>
      </appender>

</log4net>

 <startup>
   <supportedRuntime version="v4.0" sku=".NETFramework, Version="v4.0" />
 </startup>
</configuration>


11. 接著在開起專案中的AssemblyInfo.cs 加入 以下組件資訊
[assembly: log4net.Config.DOMConfigurator(ConfigFileExtension = "config", Watch = true)]

如下圖


12. 接著就可以在主程是裡面使用log4net
   
          private static log4net.ILog Log = log4net.LogManager.GetLogger("");
       
    並且可以在需要Exception 的地方加入Log.Error(""); 或 Log.Info("");  產生的log檔案會在Debug資料夾底下。檔案名稱為MyLog.txt  (可在第10.步驟的時候將名稱改掉,位置也可以修改)

















2015年6月9日 星期二

C# windowsForm ClickOnce 的部署 - 是否能夠安裝到所有使用者底下?

If you need to install / upgrade for all users on a PC, Clickonce is not an option. Clickonce is meant for installing an application for a single user without administrative rights.
You will need to create a MSI installer to distribute an application to multiple users on the same machine. There are multiple ways to deploy and update applications on clients when the client does not have administrative rights. A few examples:
  • Advertise your MSI in Active Directory, installation and upgrade does not require administrative privileges.
  • Use System Center Update Publisher (SCUP) to publish your application to Windows Server Update Services (WSUS). With WSUS you can deploy Microsoft updates, and your application. Both WSUS and SCUP are freely available for download.
  • Use Group Policy to elevate installers (not a recommended solution!), to enable non-admins to install MSIs for all users
Hope this helps.

ClickOnce 是綁定單一使用者的方式進行更新檢查,因此不行,如果windows同一作業系統底下有多個使用者,那麼該程式對於所有使用者是獨立的。
寫一個Msi做控制是個不錯的選擇......

文章來源: http://stackoverflow.com/questions/276916/click-once-all-users 

2015年5月29日 星期五

C# ListBox 如何新增ListBox裡面的item項目的背景顏色 或字體顏色

         
            ListBox預設是存放字串, 如果ListBox裡面的item要做到背景色或字型顏色的變化,就 要使用Drawitem事件調適,傳統的方法是不合適的。


           //--------產生ListBox
          main
         {
            ListBox SearchListBoxResult = new ListBox();
            SearchListBoxResult.Name = "SearchListBoxResult_ListBox";
            SearchListBoxResult.Tag = "AriesItemTitle";
            SearchListBoxResult.Left = 5;
            SearchListBoxResult.Top = 65;
            SearchListBoxResult.Width = 200;
            SearchListBoxResult.Height = 300;
            SearchListBoxResult.Items.Add(new MyListBoxItem(Color.White , "123" ));

            SearchListBoxResult.DoubleClick += SearchListBoxResult_Click;
            SearchListBoxResult.DrawItem += SearchListBoxResult_DrawItem;
            this.tabPage3.Controls.Add(SearchListBoxResult);
         
            SearchListBoxResult.DrawMode = DrawMode.OwnerDrawFixed;//----啟動drawitem事件

        }

        /// <summary> 製作一個ListBox item項目顏色的增加
        /// 製作一個ListBox item項目顏色的增加
        /// </summary>
        public class MyListBoxItem
        {
            public MyListBoxItem(Color c, string m)
            {
                ItemColor = c;//------顏色
                Message = m;//------- string 文字
            }
            public Color ItemColor { get; set; }
            public string Message { get; set; }
        }

        /// <summary>
        /// ListBox繪畫底圖的事件功能
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SearchListBoxResult_DrawItem(object sender, DrawItemEventArgs e)
        {
            ListBox Temp = new ListBox();
            for (int i = tabPage3.Controls.Count - 1; i >= 0; i--)
            {
                if (this.tabPage3.Controls[i].Name == "SearchListBoxResult_ListBox")
                    Temp = (ListBox)this.tabPage3.Controls[i];
            }
           
            MyListBoxItem item = Temp.Items[e.Index] as MyListBoxItem; // Get the current item and cast it to MyListBoxItem
            if (item != null)
            {
                e.Graphics.FillRectangle(new SolidBrush(item.ItemColor), e.Bounds);
                e.Graphics.DrawString( // mDraw the appropriate text in the ListBox
                    item.Message, // The message linked to the item
                    Temp.Font, // Take the font from the listbox
                    new SolidBrush(Color.Black), // Set the color
                    0, // X pixel coordinate
                    e.Index * Temp.ItemHeight // Y pixel coordinate.  Multiply the index by the ItemHeight defined in the listbox.
                   
                );
             
            }
            else
            {
                // The item isn't a MyListBoxItem, do something about it
            }
        }

2015年5月6日 星期三

SQLite 刪除資料後,檔案大小不會變小的解決方法 Vacuum 指令,也等於壓縮Sqlite資料

       當SQLite資料內容頻繁的做插入、刪除、此時SQLITE檔案並不會變小,這時就可以透過下面的C#語法將資料壓縮。
       筆者進行360W筆資料的移除後發現檔案大小依舊為300MB,當執行vacuum後壓縮資料庫為16MB。同時效能也可以提高。



//--插入進資料庫 這裡的資料一定為唯一的
            SQLiteConnection sqlite_conn;//----連結建立
            SQLiteCommand sqlite_cmd;//--------連結指令建立

            sqlite_conn = new SQLiteConnection(ConfigurationManager.ConnectionStrings["sqlite"].ToString());//取得sqlite位置
            sqlite_conn.Open();//--------------打開資料庫
            sqlite_cmd = sqlite_conn.CreateCommand();//--啟動資料庫指令
            sqlite_cmd.CommandText = "vacuum; ";
            sqlite_cmd.ExecuteNonQuery();//----執行

2015年5月5日 星期二

C# SQLite 在寫入資料時如何加快的方法 - 批次處理SQLite 寫入的指令 DbTransaction

SQLite 大家最知道的缺點就是寫入效率太差,但有一個批次處裡的功能可以稍微加快這方面
            效率的問題。
            筆者在處理18000筆資料寫入上傳統做法要10分左右 但使用該方法只需要2秒鐘左右



//-以下為批次處理SQLite語法
            sqlite_conn = new SQLiteConnection(ConfigurationManager.ConnectionStrings["sqlite"].ToString());//取得sqlite位置
            sqlite_conn.Open();//--------------打開資料庫
            sqlite_cmd = sqlite_conn.CreateCommand();//--啟動資料庫指令

           List<string> TempResult = new List<string>;
           trans.add("1");//---加入兩筆資料
           trans.add("2");
         

            //--批次交易處理方法
            DbTransaction trans = sqlite_conn.BeginTransaction();

            try
            {
                for (int i = 0; i < TempResult.Count; i++)//---裡面有兩筆資料
                {
                    sqlite_cmd.CommandText = "INSERT INTO QryStock (SQL) VALUES (" + TempResult[i] +")";
                    sqlite_cmd.ExecuteNonQuery();//----執行
                }


                trans.Commit(); // <-------------------批次執行上述的SQL指令

            }
            catch (Exception ex)
            {
                trans.Rollback(); // <-------------------如果有發生錯誤會中斷
                throw; // <-------------------

            }
           
           
           
            sqlite_conn.Close();

2015年2月10日 星期二

C# 取得音樂檔(例如.mp3)播放長度的方法

       using System.IO;
       using Shell32;
       using Microsoft.Win32;
       using System.Runtime.InteropServices;

        /// <summary>
        /// 取得音樂檔播放長度的方法
        /// </summary>
        /// <param name="MusicPath"></param>帶入音樂.mp3的位置 例如 C:\\hello.mp3
        /// <returns></returns>
        public int GetMediaLen2(string MusicPath)
        {
            string dirName = Path.GetDirectoryName(MusicPath);//---------取得檔案路徑 (不包含檔案)
            string SongName = Path.GetFileName(MusicPath);//-取得檔案名稱 (此處為音樂檔案.mp3)
            FileInfo fInfo = new FileInfo(MusicPath);//------------取得檔案的相關屬性
            ShellClass sh = new ShellClass();//----------------------取得文件屬性 使用microsoft的Com元                                                                   //件 Dll的Embed Interop Type(內嵌Interop類型)=false
            Folder dir = sh.NameSpace(dirName);//----------------------將檔案路徑轉為Folder的型態
            FolderItem item = dir.ParseName(SongName);//---------------將檔案轉為FolderItem的型態
            string SongTime = Regex.Match(dir.GetDetailsOf(item, -1), "\\d{2}:\\d{2}:\\d{2}").Value;
                                                                                      //取得string型態的音樂長度
            //dir.GetDetailsof(該路徑下的這個檔案 , -1 )  -1 = 所有的資料
            //Regex.Match("字串" , 找出指定的字串項目)  時間格式為 00:00:00  所以    
            //       \\d{2}:\\d{2}:\\d{2}
           
            SongTime = SongTime.Replace(':', '0');//----------------將:以0取代
            int data = int.Parse(SongTime);//--------------------------再轉為int 即為秒數
            return data;
        }


        在 dir.GetDetailsof 時 第二項參數有以下

        -1 所有資料
        0   檔案的名稱包含附檔名  (ex:  hello.mp3)
        1   檔案大小 (ex:  47.4kb)
        2   格式         (ex:  MP3 格式聲音)