none
Image 類別無法成為物件執行體? RRS feed

  • 問題

  • Dear all :

     

           我寫了一個用串列接收某特定字串"Request"後來傳送圖像,可是當收到某特定字串後,啟動傳送圖像的方法時,卻跳

         出"未將物件參考設定為物件的執行個體" 我大概debug了一下 好像問題是出在Image這個類別上, 但我有個疑問那

         就是,  這個傳送圖像的方法在button 的click事件下以及timer_tick事件下都可以正常執行傳圖的動作,這和我收到特定字

         再啟動傳送圖像 的方法有何不同? 如果是這樣 有無其他可解套的辦法.

     

            private void COM3_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                string ID = COM3.ReadExisting( );
                if (ID == "Request")
                {

                    Start_Sending_Image_Conference( );   //  傳送圖像的方法
                }
            }

     

            private void Start_Sending_Image_Conference( )

            {

                try

                   {

                        ms = new MemoryStream( );

                        IDataObject data;
                        Image bmap;

                        SendMessage(hHwnd, WM_CAP_EDIT_COPY, 0, 0);  //  Copy image to clipboard

                        data = Clipboard.GetDataObject();

                       

                         if (data.GetDataPresent(typeof(System.Drawing.Bitmap)))
                       {
                           bmap = ((Bitmap)(data.GetData(typeof(System.Drawing.Bitmap))));
                           ms.Position = 4;                    // "Image data" write to memory stream at index ==>14
                           bmap.Save(ms, ImageFormat.Jpeg);
                       }

                      // 後續還有省略.........

                   }

            }

    2008年5月8日 下午 04:45

解答

  •  

    若是 WebCam 的話,往剪貼簿送,不會用延後提出的方法,你這種寫法是針對延後提出的剪貼簿,一般存取直接用 Clipboard.GetImage 。

     

    什麼是剪貼簿延後提出?當把資料往剪貼簿送時,並不傳送資料,僅傳送支援的格式,當指定貼上格式時,才會由剪貼簿向來源要求指定格式,再由來源送出指定的格式。

     

    如果你的資料來源並不支援延後提出時,我不知道你剪貼簿為啥這樣存取。

     

    而且一般來說,大部分的軟體送出圖片是不具 System.Drawing.Bitmap 的格式,而是一般的 Bitmap 或 DIB 格式,只有用 GDI+ 包裝過的才會輸出 System.Drawing.Bitmap 的格式。

     

    另外,若是你在 button_click事件下以及Timer_Tick事件下執行正常,而 DataReceived 事件不行,則建議你把 Start_Sending_Video_Conference() 寫成委派的方式,應該是 DataReceived 事件是用另一個執行緒插斷進來,而不像 Button_Click 事件及Timer_Tick 事件都用主執行緒跑。

     

    寫成委派的程式碼就能被主執行緒或子執行緒呼叫來使用。

    2008年5月14日 上午 06:58

所有回覆

  • DataReceived

    並不會一次就把所有資料都收完,應該先有個迴圈來判斷資料的完整性,才會丟 MemoryStream 轉 Image

    2008年5月8日 下午 05:32
  •  

    To Mr.璉璉 : 我想你可能誤解我的意思了, 我的問題是在收到某特定字串後,為何不能以該字串做為判斷"傳送影像"的依據,可能是程式沒有打完整讓您誤會了.
    2008年5月13日 上午 09:00
  • 之前是我會錯意了。

     

    要能支援 System.Drawing.Bitmap 要 Office XP 以後才可以,還不是每套都支援,而從你 SendMessage 來看,似乎不像是 Office 軟體,你確定你的格式是 System.Drawing.Bitmap 嗎?

     

    我自己用的程式碼:

    Code Snippet

     

    Public Shared Function GetImage(Optional ByVal ClipboardFormat As ClipboardImageFormat = ClipboardImageFormat.All) As System.Drawing.Image

         Dim ido As System.Windows.Forms.IDataObject

         Dim ms As IO.MemoryStream

         Dim strFmt As String = ""

     

         If ClipboardFormat And ClipboardImageFormat.Bitmap Then

              strFmt = GetExistFormatName(m_BitmapFormat)

         End If

         If ClipboardFormat And ClipboardImageFormat.MetaFile And strFmt.Length = 0 Then

              strFmt = GetExistFormatName(m_MetaFileFormat)

         End If

         ido = System.Windows.Forms.Clipboard.GetDataObject

         If strFmt = "System.Drawing.Bitmap" Then

              Return ido.GetData(strFmt, True)

         Else          

              ms = ido.GetData(strFmt, True)

              Return System.Drawing.Image.FromStream(ms)

         End If

    End Function

     

     

    也就是說,如果資料來源不是 System.Drawing.Bitmap 的時候,GetData 傳回的是 MemoryStream ,所以把記憶體流直接塞給 Image.FromStream 轉換。

     

    上面這段程式碼用在:擷取Word 檔內圖片工具

    2008年5月13日 上午 09:58
  • 哈哈,寫錯了~

    是用在上面那個東西裡面沒錯,不過是寫在這篇:

    [VBNET] 關於剪貼簿延後提出的處理

     

    2008年5月13日 上午 10:01
  • To Mr.  璉璉: 這個SendMessage(hHwnd, WM_CAP_EDIT_COPY, 0, 0)指的是webcam在window上顯示的影像,這跟什麼office xp沒有關係. 不好意思 !我還是把完整的程式碼貼上可能會比較清楚 ,而我要做的是影像傳輸的交握,我現在的問題是 在串列接收事件下收到字串為何會產生"並未將物件參考設定為物件執行個體" ,同樣是事件為何在button_click事件下以及Timer_Tick事件下執行Start_Sending_Video_Conference()都不會有問題這是為什麼?有什麼方法可以解決這樣的問題

     

     

     

     

     
    Code Snippet

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.Runtime.InteropServices;
    using System.Drawing.Imaging;
    using System.Threading;
    using System.IO;
    using System.IO.Ports;


    namespace Video_Conference
    {
     /// <summary>
     /// Summary description for Form1.
     /// </summary>
     public class Form1 : System.Windows.Forms.Form
     {
            private System.Windows.Forms.SaveFileDialog saveFileDialog1;
            private TextBox IP_textBox;
            private TextBox device_number_textBox;
            private Label label2;
            private Button button1;
            private Button button2;
            private System.Windows.Forms.Timer timer1;
            private SerialPort COM3 = new SerialPort();
            private SerialPort COM4 = new SerialPort("COM4",4800,Parity.None,8,StopBits.One);
      #region WebCam API
      const short WM_CAP = 1024;
      const int WM_CAP_DRIVER_CONNECT = WM_CAP + 10;
      const int WM_CAP_DRIVER_DISCONNECT = WM_CAP + 11;
      const int WM_CAP_EDIT_COPY = WM_CAP + 30;
            const int WM_CAP_DLG_VIDEOFORMAT = WM_CAP + 41;
            const int WM_CAP_DLG_VIDEOSOURCE = WM_CAP + 42;
      const int WM_CAP_SET_PREVIEW = WM_CAP + 50;
      const int WM_CAP_SET_PREVIEWRATE = WM_CAP + 52;
      const int WM_CAP_SET_SCALE = WM_CAP + 53;
      const int WS_CHILD = 1073741824;
      const int WS_VISIBLE = 268435456;
      const short SWP_NOMOVE = 2;
      const short SWP_NOSIZE = 1;
      const short SWP_NOZORDER = 4;
      const short HWND_BOTTOM = 1;
      int iDevice = 0;
            private Button button3;
            private Button button4;
            private Button GPS_Open;
            int hHwnd;
      [System.Runtime.InteropServices.DllImport("user32", EntryPoint="SendMessageA")]
      static extern int SendMessage(int hwnd, int wMsg, int wParam,  [MarshalAs(UnmanagedType.AsAny)]
       object lParam);
      [System.Runtime.InteropServices.DllImport("user32", EntryPoint="SetWindowPos")]
      static extern int SetWindowPos(int hwnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
      [System.Runtime.InteropServices.DllImport("user32")]
      static extern bool DestroyWindow(int hndw);
      [System.Runtime.InteropServices.DllImport("avicap32.dll")]
            static extern int capCreateCaptureWindowA(string lpszWindowName, int dwStyle, int x, int y, int nWidth, short nHeight, int hWndParent, int nID);
      [System.Runtime.InteropServices.DllImport("avicap32.dll")]
      static extern bool capGetDriverDescriptionA(short wDriver, string lpszName, int cbName, string lpszVer, int cbVer);
      
            private void OpenPreviewWindow()
      {
       int iHeight = 84;
       int iWidth = 112;
       //
       //  Open Preview window in picturebox
       //
       hHwnd = capCreateCaptureWindowA(iDevice.ToString (), (WS_VISIBLE | WS_CHILD), 0, 0, 640, 480, picCapture.Handle.ToInt32(), 0);
       //
       //  Connect to device
       //
       if (SendMessage(hHwnd, WM_CAP_DRIVER_CONNECT, iDevice, 0) == 1)
       {
        //
        // Set the preview scale
        //
        SendMessage(hHwnd, WM_CAP_SET_SCALE, 1, 0);
        //
        // Set the preview rate in milliseconds
        //
        SendMessage(hHwnd, WM_CAP_SET_PREVIEWRATE, 500, 0);
        //
        // Start previewing the image from the camera
        //
        SendMessage(hHwnd, WM_CAP_SET_PREVIEW, 1, 0);
        //
        //  Resize window to fit in picturebox
        //
        SetWindowPos(hHwnd, HWND_BOTTOM, 0, 0, iWidth,iHeight, (SWP_NOMOVE | SWP_NOZORDER));
       }
       else
       {
        //
        //  Error connecting to device close window
        // 
        DestroyWindow(hHwnd);
       }
      }
      private void ClosePreviewWindow()
      {
       //
       //  Disconnect from device
       //
       SendMessage(hHwnd, WM_CAP_DRIVER_DISCONNECT, iDevice, 0);
       //
       //  close window
       //
       DestroyWindow(hHwnd);
      }
      #endregion

            internal System.Windows.Forms.Button btnStop;
      internal System.Windows.Forms.Button btnStart;
            internal System.Windows.Forms.PictureBox picCapture;
            private IContainer components;
        
      public Form1()
      {
       //
       // Required for Windows Form Designer support
       //
       InitializeComponent();
                COM3.DataReceived += new SerialDataReceivedEventHandler(COM3_DataReceived);
       //
       // TODO: Add any constructor code after InitializeComponent call
       //
      }
            private void COM3_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
             
                string ID = COM3.ReadExisting();
                if (ID == "Send")
                {
                    Start_Sending_Video_Conference();
                
                }
               
            }

        
      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      protected override void Dispose( bool disposing )
      {
       if( disposing)
       {
        if (components != null)
        {
         components.Dispose();
        }
       }
       base.Dispose( disposing );
      }


                   /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main()
      {
       Application.Run(new Form1());
      }
         
            MemoryStream ms;


            private void Start_Sending_Video_Conference()
            {
                try
                {

                    ms = new MemoryStream();// Store it in Binary Array as Stream


                    IDataObject data;
                    Image bmap;

                    ////  Copy image to clipboard
                    SendMessage(hHwnd, WM_CAP_EDIT_COPY, 0, 0);

                    ////  Get image from clipboard and convert it to a bitmap
                    data = Clipboard.GetDataObject();

                    if (data.GetDataPresent(typeof(System.Drawing.Bitmap)))
                    {
                        bmap = ((Image)(data.GetData(typeof(System.Drawing.Bitmap))));
                        ms.Position = 14;                    // "Image data" write to memory stream at index ==>14
                        bmap.Save(ms, ImageFormat.Jpeg);
                    }

                      byte[] gpstime = GPStime();
                      ms.Position = 0;                         // "UTC time" write to memory stream at index ==> 0
                      ms.Write(gpstime, 0, gpstime.Length);    // UTC 佔10個byte

                    ms.Position = 10;                        // "image data Length byte set" write to memory stream at index ==> 10
                    int imagelength = (int)(ms.Length - 14);
                    byte[] imagelenconvert = BitConverter.GetBytes(imagelength);
                    ms.Write(imagelenconvert, 0, 4);

                    byte[] imagedata = ms.ToArray();


                    send_data(imagedata);

                    ms.Flush();

                    ms.Close();

                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.Message, "Video Conference Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
          
            private void send_data(byte[] alldatawrite)
            {
                COM3.Write(alldatawrite, 0, alldatawrite.Length);
            }
      private void btnStart_Click(object sender, System.EventArgs e)  // Turn on QuickCam and show in the window preview
      {
       iDevice = int.Parse (device_number_textBox.Text);
       OpenPreviewWindow();
      }
      private void btnStop_Click(object sender, System.EventArgs e)  //Turn off QuickCam and stop to sending image
      {
       ClosePreviewWindow();
                timer1.Enabled = false;
      }
      private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
      {
       if (btnStop.Enabled)
       {
        ClosePreviewWindow();
       }

      }

            private void button1_Click(object sender, EventArgs e)
            {
               // button1.Enabled = false;
               // myth = new Thread(new System.Threading.ThreadStart(Start_Receiving_Video_Conference)); // Start Thread Session
               // myth.Start(); // Start Receiveing Camera
            }

            private void timer1_Tick(object sender, EventArgs e)
            {
                Start_Sending_Video_Conference(); //execute Start_Sending_Video_Conference interval 1 second each time
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                COM3.PortName = "COM3";
                COM3.BaudRate = 38400;
                COM3.Parity = Parity.None;
                COM3.StopBits = StopBits.One;
                COM3.DataBits = 8;
               
                //COM4.Open();
            }

            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                try
                {
                    ClosePreviewWindow();
                   // mytcpl.Stop();
                   // myth.Abort();
                }
                catch (Exception){}
            }

            private void button2_Click(object sender, EventArgs e)
            {
               
                if (COM3.IsOpen)
                {
                    COM3.Close();
                }
                COM3.Open();
               //timer1.Enabled = true;
               // Start_Sending_Video_Conference();
                 
            }

            private void button3_Click(object sender, EventArgs e)  // change video format,resolution etc.
            {
                SendMessage(hHwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0);
            }

            private void button4_Click(object sender, EventArgs e)  // change video source like other video device
            {
                SendMessage(hHwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0);
            }

            public byte[] GPStime()
            {
                string sData = "";
                while (true)
                {
                    string line = "";
                    sData = COM4.ReadLine();
                    string[] st = sData.Split(',');
                    if (st[0] == "$GPRMC")
                    {
                        line = st[1];
                        byte[] msg = System.Text.Encoding.ASCII.GetBytes(line);
                        return msg;
                    }
                    //若msg擺在此傳回的話要重複執行三次才可傳回
                }
            }

            private void GPS_Open_Click(object sender, EventArgs e)
            {
                if (COM4.IsOpen)
                {
                    COM4.Close();
                }

                COM4.Open();
            }
           

           
     }
    }

     

     

    2008年5月14日 上午 06:15
  •  

    若是 WebCam 的話,往剪貼簿送,不會用延後提出的方法,你這種寫法是針對延後提出的剪貼簿,一般存取直接用 Clipboard.GetImage 。

     

    什麼是剪貼簿延後提出?當把資料往剪貼簿送時,並不傳送資料,僅傳送支援的格式,當指定貼上格式時,才會由剪貼簿向來源要求指定格式,再由來源送出指定的格式。

     

    如果你的資料來源並不支援延後提出時,我不知道你剪貼簿為啥這樣存取。

     

    而且一般來說,大部分的軟體送出圖片是不具 System.Drawing.Bitmap 的格式,而是一般的 Bitmap 或 DIB 格式,只有用 GDI+ 包裝過的才會輸出 System.Drawing.Bitmap 的格式。

     

    另外,若是你在 button_click事件下以及Timer_Tick事件下執行正常,而 DataReceived 事件不行,則建議你把 Start_Sending_Video_Conference() 寫成委派的方式,應該是 DataReceived 事件是用另一個執行緒插斷進來,而不像 Button_Click 事件及Timer_Tick 事件都用主執行緒跑。

     

    寫成委派的程式碼就能被主執行緒或子執行緒呼叫來使用。

    2008年5月14日 上午 06:58
  • To Mr. 璉璉 : 想再請問一下這個Start_Sending_Video_Conference() 要怎麼用委派的方式來做,我試了很多次一樣會跳出"並未將物件參考設定為物件執行個體"就是不知該怎麼弄,因為我對委派不熟

    如下所示我這樣寫對嗎?

     

     

       

    Code Snippet

    public delegate void ImageSenddelegate();     //   Declaration  delagate

       public class Form1 : System.Windows.Forms.Form

     

            ...............................

            ..............................

            ..............................

          private void COM3_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
             
                string ID = COM3.ReadExisting();
                if (ID == "Send")
                {
                    ImageSenddelegate imagesenddelagate = new ImageSenddelegate(Start_Sending_Video_Conference);
                    imagesenddelagate( );
                }
               
            }
            ....................................

             ...................................

          private   void  Start_Sending_Video_Conference()
            {

                ...........................

               ...........................

                ........................

            }

     

     

     

    2008年5月14日 下午 05:00