none
PictureboxにPCの画面を表示させる。 RRS feed

  • 質問

  • 自分は今学生なのですが、プログラムの勉強の一環としてネットワークストリームをかいして、別のPCの画面をリアルタイムで見れるようなアプリケーションを作りたいと思ったのですが、うまく動作をしなくて困っています。ソースコードでいうと、

    -----クライアント側-------
                    Rectangle rec;

                    rec = Screen.PrimaryScreen.Bounds;

                    Bitmap bmp = new Bitmap(rec.Width,rec.Height);
                    MemoryStream ms = new MemoryStream();
                    TcpClient c = new TcpClient(ipAddr, 8888);
                    NetworkStream netstream = c.GetStream();

                    while (true)
                    {
                        using (Graphics g = Graphics.FromImage(bmp))
                        {
                            g.CopyFromScreen(rec.X, rec.Y, 0, 0, rec.Size, CopyPixelOperation.SourceCopy);
                        }

                        bmp.Save(ms, ImageFormat.Jpeg);
                        MessageBox.Show(ms.Length.ToString());
                        ms.WriteTo(netstream);

                        netstream.Flush();
                        ms.Flush();

                        Thread.Sleep(100);
                    }

    -----サーバ側-----               
                    NetworkStream netStram;
                    MemoryStream ms = new MemoryStream();
                    Byte[] byt = new Byte[1000000];//どれだけの情報がくるかわからないから大きめにとった。

                    netStram = client.GetStream();

                    while (true)
                    {
                        try
                        {
                            netStram.Read(byt, 0, 1000000);
                            ms.Write(byt, 0, 1000000);
                           
                            form1.Invoke(new MethodInvoker(delegate()//ここはメインスレッド(?)とは違うので
                            {
                                form1.pb1_gazou_hyouzi(ms);
                            }));
                           
                            ms.Flush();
                            netStram.Flush();
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show(e.ToString());
                        }
                       
                        Thread.Sleep(100);
                    }



    public void pb1_gazou_hyouzi(MemoryStream ms)//Form1に書いてあるメソッドです。
    {
            pictureBox1.Image = System.Drawing.Image.FromStream(ms);
            pictureBox1.Refresh();
    }

    このようなプログラムを書いたのですが、ピクチャーボックスに表示される画像は最初の一枚目(起動直後の画面の画像)だけしか表示されません。
    またクライアント側のメモリストリーム「ms」の長さを計ってみたところ、時間がたつにつれてどんどん情報量が大きくなっていることがわかりました。

    また、そもそも画面をリアルタイムで表示させる方法としてこの方法はどうなんでしょうか?正直なところ、元になるようなアルゴリズムがなく、自分の知識の知ってる範囲で考えたので、かなり無理やりな方法にはなっていないでしょうか?

    正直な所、どこがわからないか分からないという、かなり失礼な質問だと思いますが、よければお返事を頂けるとありがたいです。

    2009年4月1日 6:31

回答

  • MemoryStream.Flushの呼び出しは効果がありません。
    http://msdn.microsoft.com/ja-jp/library/system.io.memorystream.flush.aspx


    現状、MemoryStreamにはBitmapが100ms毎に書き込まれていくため、MemoryStreamには1枚、2枚、3枚…といったようにどんどん枚数が増えていきます。
    そのデータ列を全てNetworkStreamで送りつけているので、最初の絵しか表示を期待できないのでは?

    恐らく、あるべき姿としてはMemoryStreamの内容をクリアすることだと思います。(方法は調べてみて下さい)
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク SE_lain 2009年4月6日 13:59
    2009年4月1日 14:26
    モデレータ

すべての返信

  • MemoryStream.Flushの呼び出しは効果がありません。
    http://msdn.microsoft.com/ja-jp/library/system.io.memorystream.flush.aspx


    現状、MemoryStreamにはBitmapが100ms毎に書き込まれていくため、MemoryStreamには1枚、2枚、3枚…といったようにどんどん枚数が増えていきます。
    そのデータ列を全てNetworkStreamで送りつけているので、最初の絵しか表示を期待できないのでは?

    恐らく、あるべき姿としてはMemoryStreamの内容をクリアすることだと思います。(方法は調べてみて下さい)
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク SE_lain 2009年4月6日 13:59
    2009年4月1日 14:26
    モデレータ
  • お返事ありがとうございます。

    なるほど、メモリーストリームの内容はfluhでは消えてなかったのですね。
    内容をクリアする方法はわからなかったのですが、その代りにシークメソッドを使って、一番初めから書き込む様にするとデータの大きさは一定になりました。

    ただ、やはり最初の絵しか表示されません。他にもおかしい点があるのでしょうか?

    2009年4月2日 7:12
  • ただ、やはり最初の絵しか表示されません。他にもおかしい点があるのでしょうか?
    画像を受け取る側のMemoryStreamはどうなっているかは確認されているのでしょうか?
    同じように溜まっているのではないかと気になります。

    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年4月2日 14:22
    モデレータ
  • なんどもお返事いただきありがとうございます。

    memorystreamの長さの確認の仕方がわからなかったので、ためしにシークを一番初めにもっていくとリアルタイムで更新することができました。
    ありがとうございます。

    このようなあいまいな質問にもお答えいただきとても感謝です。
    2009年4月6日 13:59