C# – Chụp ảnh toàn bộ trang Web (Webpage capture)

Sử dụng một WebBrowser control để nạp trang web, bạn có thể chụp được ảnh màn hình dựa vào kích thước của tài liệu trong WebBrowser thông qua phương thức Graphics.CopyFromScreen(). Tuy nhiên, WebBrowser đã hỗ trợ sẵn phương thức DrawToBitmap() giúp bạn làm việc này.
(Từ Câu hỏi của bạn Án Bình Trọng)

 

Download demo+sourcecode (16KB)

Screenshot:

Phương pháp chụp hình trang web này dựa vào việc tạo một WebBrowser và phóng to cửa sổ để hiển thị toàn bộ trang web. Sau đó ta sẽ dùng phương thức DrawToBitmap() để lưu ảnh vào một Bitmap.

Để đảm bảo việc chụp ảnh trang web chỉ diễn ra một lần, ta cần làm công việc này trong sự kiện WebBrowser.DocumentCompleted, và sử dụng thêm property WebBrowser.ReadyState để kiểm tra việc nạp xong trang web.

Chụp ảnh

Phương thức CaptureWebPage() sau cung cấp thêm việc hiển thị tiến trình làm việc của WebBrowser thông qua một progressBar1:

void CaptureWebPage(string url)
{
    Cursor.Current=Cursors.WaitCursor;
    progressBar1.Show();
    if (_browser == null) {
        _browser = new WebBrowser();
        _browser.ProgressChanged += (sender,e) =>
        {
             progressBar1.Value = (int)(((double)e.CurrentProgress / e.MaximumProgress)*100);
        };

        _browser.DocumentCompleted += (sender, e) =>
        {
            if (_browser.ReadyState == WebBrowserReadyState.Complete) {

                int width = _browser.Document.Body.ScrollRectangle.Width;
                int height =_browser.Document.Body.ScrollRectangle.Height;

                _bitmap = new Bitmap(width,height);

                _browser.Size = _bitmap.Size;
                _browser.DrawToBitmap(_bitmap,_browser.Bounds);
                _browser.Stop();

                pictureBox1.Image = _bitmap;
                pictureBox1.Size = _bitmap.Size;

                lblImageSize.Text= String.Format("{0} x {1} pixels",_bitmap.Width,_bitmap.Height);

                progressBar1.Hide();
            }
        };
    }
    _browser.Navigate(url);
}

Thay đổi kích thước ảnh

Vì việc resize sẽ làm thay đổi ảnh nên cần sử dụng một đối tượng Bitmap (thành viên của lớp) để lưu lại ảnh ban đầu. Ví dụ sau sử dụng một NumericUpDown cho phép người dùng thay đổi kích thước theo phần trăm, từ đó tính ra kích thước mới (width x height):

void NumPercentValueChanged(object sender, EventArgs e)
{
    if(_bitmap==null)
        return;
    float percent=(float)(numPercent.Value/100);
    Bitmap bmp=new Bitmap((int)(_bitmap.Width*percent),(int)(_bitmap.Height*percent));
    lblImageSize.Text= String.Format("{0} x {1} pixels",bmp.Width,bmp.Height);
    Graphics g=Graphics.FromImage(bmp);
    g.DrawImage(_bitmap,0,0,bmp.Width,bmp.Height);
    pictureBox1.Image=bmp;
    pictureBox1.Size=bmp.Size;
}

Lưu ảnh

Sử dụng phương thức Image.Save(), phương thức này chấp nhận một tham số ImageFormat dành cho định dạng ảnh:

void BtnSaveClick(object sender, EventArgs e)
{
    if(saveFileDialog1.ShowDialog()==DialogResult.OK)
    {
        ImageFormat format;
        switch(saveFileDialog1.FilterIndex)
        {
            case 1:
                format=ImageFormat.Png;
                break;
            case 2:
                format=ImageFormat.Jpeg;
                break;
            default:
                format=ImageFormat.Bmp;
                break;
        }
        pictureBox1.Image.Save(saveFileDialog1.FileName,format);
    }
}

Note:Để sử dụng trong ASP.NET project, bạn cần add references các assembly cần thiết của WinFoms.

https://yinyangit.wordpress.com

Advertisements

13 thoughts on “C# – Chụp ảnh toàn bộ trang Web (Webpage capture)

  1. Mình đang cần convert HTML (bao gồm cả javarcript) thành Pdf trong trang Web của mình. Mình định thử qua cách của bạn. Mình đã add Reference nhưng sự kiện : _browser.DocumentCompleted
    ko xảy ra bao giờ nên thành ra mình ko DrawBitmap được. Bạn có thể giúp mình được không. Và bài toán của mình có thể giải quyết theo hướng khác được ko? Bạn giúp mình nhé. Mình mới làm quen với ASP.NET nên vẫn còn nhiều điểu không rõ.
    Thank bạn!

    Trả lời
  2. Sau khi kiểm tra thì mình nhận thấy việc chạy WebBrowser trong ASP.NET tương đối phức tạp và liên quan tới nhiều vấn đề khác.

    Trong trường hợp của bạn, bởi vì PDF không phải là hình ảnh và có nhiều định dạng phức tạp, mình nghĩ bạn cần tìm kiếm các thư viện tạo PDF miễn phí hoặc open source để sử dụng. Bạn có thể tham khảo trên một số trang như codeproject, stackoverflow để thử và chọn thư viện mà bạn thấy hiệu quả nhất.

    Trả lời
  3. Hii, mình cũng đã thử dùng WebBrowser, nó liên quan tới Thread nên phức tạp thật. Trang web của mình dùng Google chart API (http://code.google.com/apis/chart/interactive/docs/gallery.html), mình cũng đã dùng một số thư viện như Essential Objects nhưng gặp một số vấn đề như sau:
    + Các thư viện này hỗ trợ CSS, jQuery.. nhưng khi convert thành PDF, một số chart bị mất đi. (Dùng cách của bạn thì tương đối ổn, các chart ko bị mất hii).
    + Vướng mắc về vấn đề license.
    Các thư viện miễn phí hỗ trợ tạo PDF cho ASP.NET ít ( mình chưa tìm được 😦 ) nên vấn đề của mình vẫn treo ở đó :(. Bạn giúp mình được không.
    P/s : Mình đang là sinh viên và hình như bạn hơn tuổi mình cũng nhiều. Chắc mình phải gọi bạn (ít nhất) là chị hoặc anh rồi. Hii.

    Trả lời
  4. Vấn đề này mình ko rành và cũng chưa từng tìm hiểu qua nên khó có thể giúp được bạn. Bạn có thể tìm kiếm thêm và tham khảo các bạn cùng lớp xem sao.

    p/s: Bạn xưng hô sao cũng được, hiện tại mình vẫn còn đi học. Hơn nữa cách xưng hô này ko cần phân biệt tuổi tác.

    Trả lời
  5. Anh Ying Yang cho em hỏi khi thay đổi giá trị của đối tượng trên trang web ví dụ như nhập giá trị vào textbox rùi sau đó chụp lại toàn bộ trang web thì với source code của anh ở trên có được không ạ, em nghĩ là không được vì có sự kiện chờ load hết toàn bộ trang web rùi mới bắt đầu chụp. Vậy có cách nào chụp toàn bộ trang web với dữ liệu của mình nhập vào không ạ?
    Em cảm ơn anh nhiều

    Trả lời
    • .NET hỗ trợ các class để xử lý HTML DOM trong namespace System.Windows.Forms. Ví dụ sau khi load trang xong, bạn có thể đổi nội dung của một thẻ input có id = searchBox như sau:

      HtmlElement element = webBrowser1.Document.GetElementById(“searchBox”);
      element.InnerText = “Yin Yang”;

      Trả lời
      • Cảm ơn anh.
        Nhưng với trang web có nhiều input thay đổi thì sẽ viết rất dài và nếu truyền địa chỉ trang web khác thì ta phải thay đổi source code phải không anh.

      • Tùy theo mục đích của bạn, tùy theo từng trang web. API của .NET hỗ trợ khá đầy đủ các phương thức để bạn thao tác với tài liệu html rồi. Nếu bạn đưa ra trường hợp cụ thể thì mình sẽ giúp đưa ra cách làm hiệu quả nếu có thể.

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s