none
win form內崁 WebBrowser ?? RRS feed

  • 問題

  • Hello,

    I embed a WebBrowser in the web form, and show a page in it.

    If the page is a Frame based page. It is possible to force the WebBrowser to show a specific frame.

    Furthermore, how can I save the frame content into JPG ?

    For example, the page has 3 frames (LEFT, CENTER, and RIGHT), I just want to show the LEFT and CENTER frame in the WebBrowser, and I want to save the CENTER into JPG. Is it possible to do this ?

     

    Eric

     

    2006年11月24日 上午 07:02

解答

  • 看了一下您提供的網站, 發現他有好幾層的 Frame. 分析一下結構, 會發現地圖圖檔在第三層的 MapFrame 中, 並且圖檔所在 Html 元件的 Name 為 "theImage", 如下

    <img name="theImage" src="port_macao_jupiter2111211686846.png" border="0" height="596" hspace="0" vspace="0" width="535">

    做法如下,
    1. 一層層去尋找 WebBrowser 中, Name="MapFrame" 的 Frame.
    2. 得到這 MapFrame 後, 用 MapFrame.Document.Images["theImage"].GetAttribute("src"), 取得 "theImage" 地圖圖檔的 URL.
    3. 根據 2 所得到的 URL 把圖檔抓回來存檔.

    寫了個 Sample 供您參考,

    Form 的部份, 只有放幾個 Component

        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.WebBrowser webBrowser1;

    Code 的部份
    ..........
    using System.Net;
    using System.IO;

    namespace SaveFrameImage
    {
        public partial class Form1 : Form
        {
            private const string targetFrame = "MapFrame";
            private const string targetImage = "TheImage";
            private const string imageFilename = "map.png";

            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                webBrowser1.Navigate(textBox1.Text);
            }

            private void button2_Click(object sender, EventArgs e)
            {
                findMap(webBrowser1.Document.Window.Frames, targetFrame);
            }

            private bool findMap(HtmlWindowCollection wnds, string framename)
            {
                bool done = false;

                for (int i = 0; (!done) && (i < wnds.Count); i++)
                {
                    if (wnds[ i ].Name == framename)                  // check frame's name == "MapFrame"?
                    {
                        done = processMapFrame(wnds[ i ].Document);
                    }
                    else if (wnds[ i ].Frames.Count > 0)
                        done = findMap(wnds[ i ].Frames, framename);  // recursive call to retrieve all frames
                }

                return done;
            }

            private bool processMapFrame(HtmlDocument hdoc)
            {
                string imgurl = hdoc.Images[targetImage].GetAttribute("src");
                
                // Save image URL into a Image File.
                try
                {
                    WebRequest request = WebRequest.Create(imgurl);
                    WebResponse response = request.GetResponse();
                    Stream responseStream = response.GetResponseStream();
                    Bitmap bmp = new Bitmap(responseStream);
                    bmp.Save(imageFilename, System.Drawing.Imaging.ImageFormat.Png);
                }
                catch (System.Net.WebException)
                {
                    MessageBox.Show("There was an error opening the image file. Check the URL");
                }

                return true;
            }
        }
    }

    2006年11月29日 上午 02:26

所有回覆

  • 1. 可以用下面的 Code 取得 webBrowser中的所有 Frame, 以及每個 Frame 的資料,
        然後把 WebBrowser 導向到特定的 Frame.

       HtmlElementCollection frames = webBrowser1.Document.GetElementsByTagName("frame");
       String URL = String frames[x].GetAttribute("src"); // x 是特定 frame 的 index
       webBrowser1.Navigate(URL);

    2. 如何把 webBrowser 的內容存成 Image, 請參考,
        http://www.codeproject.com/useritems/XML_Tool.asp

    3. 關於您想做的, 只 Show Left, Right Frame, 並把 Center frame 存成影像檔, 是做得
        到的. 根據 1, 我們可以取得所有的 frame; 根據 2, 我們可以把特定的 Frame 存
        成影像檔. 最後, 把存成影像檔的 frame 清除掉, 用 Frame.OuterHtml="", 這樣應該
        就可以達到您想要的.

    2006年11月26日 上午 01:28
  • Thanks for your reply. But I can't get the solution.

    There is a web map site, I want to use it to find a location and save the map image into file. Would you please to teach me how can I do that or give me some example?

    Web site: http://www.gis.gov.mo/website/emacau/macao1.htm

    search procedures:

    - after load completely, click on the "Building Location" in the left frame.

    - enter "Pou" in the "Your Keyword" text field

    - Click "Go" and you will have a search result window.

    - Click on the first result, you will get the map.

     

    My question is that how can I save the map image (PNG) into file ?

     

    Best regards,

    Eric

     

     

    2006年11月27日 上午 07:03
  • 看了一下您提供的網站, 發現他有好幾層的 Frame. 分析一下結構, 會發現地圖圖檔在第三層的 MapFrame 中, 並且圖檔所在 Html 元件的 Name 為 "theImage", 如下

    <img name="theImage" src="port_macao_jupiter2111211686846.png" border="0" height="596" hspace="0" vspace="0" width="535">

    做法如下,
    1. 一層層去尋找 WebBrowser 中, Name="MapFrame" 的 Frame.
    2. 得到這 MapFrame 後, 用 MapFrame.Document.Images["theImage"].GetAttribute("src"), 取得 "theImage" 地圖圖檔的 URL.
    3. 根據 2 所得到的 URL 把圖檔抓回來存檔.

    寫了個 Sample 供您參考,

    Form 的部份, 只有放幾個 Component

        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.WebBrowser webBrowser1;

    Code 的部份
    ..........
    using System.Net;
    using System.IO;

    namespace SaveFrameImage
    {
        public partial class Form1 : Form
        {
            private const string targetFrame = "MapFrame";
            private const string targetImage = "TheImage";
            private const string imageFilename = "map.png";

            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                webBrowser1.Navigate(textBox1.Text);
            }

            private void button2_Click(object sender, EventArgs e)
            {
                findMap(webBrowser1.Document.Window.Frames, targetFrame);
            }

            private bool findMap(HtmlWindowCollection wnds, string framename)
            {
                bool done = false;

                for (int i = 0; (!done) && (i < wnds.Count); i++)
                {
                    if (wnds[ i ].Name == framename)                  // check frame's name == "MapFrame"?
                    {
                        done = processMapFrame(wnds[ i ].Document);
                    }
                    else if (wnds[ i ].Frames.Count > 0)
                        done = findMap(wnds[ i ].Frames, framename);  // recursive call to retrieve all frames
                }

                return done;
            }

            private bool processMapFrame(HtmlDocument hdoc)
            {
                string imgurl = hdoc.Images[targetImage].GetAttribute("src");
                
                // Save image URL into a Image File.
                try
                {
                    WebRequest request = WebRequest.Create(imgurl);
                    WebResponse response = request.GetResponse();
                    Stream responseStream = response.GetResponseStream();
                    Bitmap bmp = new Bitmap(responseStream);
                    bmp.Save(imageFilename, System.Drawing.Imaging.ImageFormat.Png);
                }
                catch (System.Net.WebException)
                {
                    MessageBox.Show("There was an error opening the image file. Check the URL");
                }

                return true;
            }
        }
    }

    2006年11月29日 上午 02:26
  • Hi Vincent,

    Thank you very much for your answer, it works very well and thanks again.

    Another problem, is it possible to simulate the Input and Mouse click for the web site but not directly on the web site.

     

    The following is the search procedures:

    after load completely, click on the "Building Location" in the left frame.

    - enter "Pou" in the "Your Keyword" text field

    - Click "Go" and you will have a search result window.

    - Click on the first result, you will get the map.

     

    How can I simulate clicking on "Building Location" in C# but not in the webbrowser page?

    And the Keywork is input in C# TextBox and also simulate click on the "Go" button.

    Finally, it will popup a result window, can it also be simulating clicking on the "result link" ?

     

    Best regards,
    Eric

     

    2006年11月29日 上午 06:44
  • 因為這個網站用了大量的 JavaScript, 所以您可能要研究一下, 那些動作會 call 哪些 JavaScript 的 Function.

    另外, .Net 2.0 的 HtmlDocument 提供一個 Method, InvokeScript, 可以讓您直接 Invoke 網頁中的 JavaScript Function.

    請參考  http://msdn2.microsoft.com/en-US/library/be9zzz62(vs.80).aspx

    究竟能不能全部模擬出來, 我沒實驗, 不能確定. 如果您實驗的話, 我的建議如下,

    先了解每個動作參與的元件有哪些? 會 Call 到哪些 JavaScript Function?
    然後嘗試用 InvokeScript 的方式呼叫看看, 試試看能不能 work.

    至於有些要填值的部分, 如 Text Field, 可以先取得該 HTML 元件, 再修改他的 innerHTML, 或是 innerText.

    2006年11月29日 上午 08:29
  • Hi Vincent,

     

    I tried to study, but don't understand very well. Could you please to give me an example for reference ?

     

    Best regadrs,
    Eric

     

    2006年11月30日 上午 09:34
  • 我想, 您要先試著把這個網頁相關的動作分析出來.

    例如, 當你 Click Go Button 時, 他做了什麼? 從 HTML 的 Source 裡可以看到, 他去 Call doAttrSearch() 這個 JavaScript Function. 有了這樣的結果, 就可用前面提到的 InvokeScript 的方式, 去呼叫 doAttrSearch().

    // 假設這樣可以取得 Go Button 的 HTML 元件
    HtmlElement btnGo = frame.Document.All.GetElementsByName("btnSearch")[0];

    // 然後用 InvokeScript 去呼叫  JavaScript function
    btnGo.Document.InvokeScript("doAttrSearch");

    所以, 您必須要先了解這個網頁的所有動作, 在整合上才會順手.

    2006年12月1日 上午 02:58
  • Hi Vincent,

    I got it, thanks. But, how can I submit a Form.

     

    For example,

     

    <form action="/something.asp" method="post">

        <input type="submit" name="submitBtn" value="Submit">

        <input type="button" name="clearBtn" value="Clear" onClick="....">

    </form>

     

    How can I simulate clicking on "submitBtn" or "clearBtn" ?

     

    Eric

     

    2006年12月1日 上午 07:51
  • 關於 Submit Form Data 到 Server 的做法, 請參考,
    http://msdn2.microsoft.com/en-us/library/debx8sh9.aspx

    對於 Button Click,
    通常 onClick 都是呼叫一個 JavaScript Function, 這種狀況, 就用 InvokeScript.

    如果不是呼叫一個 Function, 就看那段 Code 做些什麼? 想辦法做出來, 例如,

    <input id="Button1" type="button" value="button" onclick=alert('Hello!')"/>

    就可用  webBrowser1.Document.Window.Alert("Hello!") 來模擬.

    2006年12月1日 下午 01:23