[VB.NET] 차근차근 크롬 브라우저 만들기 - 3. 기본기능

2023. 2. 8. 09:00VB.NET/Chrome Browser

이번 강좌에서는 뒤로, 앞으로, 새로고침, 홈으로 등 브라우저의 가장 기본이 되는 기능을 구현해보자. 겸사겸사 VB.NET에서 툴바를 사용하는 방법도 알아보자. 첫 강좌에서 얘기했듯이 강좌를 위한 프로젝트이니 사용자 편의성이나 자잘한 오류처리등은 무시하고 넘어가도록 한다.

메인폼에서 텍스트상자(TextURL)와 이동버튼(ButtonNavigate)을 화면 아래로 이동시킨 후 도구상자에서 ToolStrip을 추가하자. 코딩에서 ToolStrip을 사용할 일이 거의 없으니 이름은 그냥 기본생성된 ToolStrip1으로 놔두고 진행하자.

사실 모든 기능은 ChromiumWebBrowser 컨트롤이 지원해주니 우리는 그냥 버튼을 만들어서 ChromiumWebBrowser에서 제공하는 함수를 호출하면 된다.

ToolStrip에 버튼을 네개 만들고 각각 아래 속성을 설정하자.

Name DisplayStyle Text
ButtonBack Text &Back
ButtonForward Text &Forward
ButtonReload Text &Reload
ButtonHome Text &Home

각 버튼을 더블클릭해서 이벤트 핸들러 생성후 아래 현재까지의 전체 소스를 확인해서 필요한 부분을 입력하자.

Imports CefSharp
Imports CefSharp.WinForms

Public Class FormBrowser

    Private WithEvents BrowserMain As CefSharp.WinForms.ChromiumWebBrowser = Nothing
    Private Delegate Sub ControlCallBack()
    Private HomePage As String

    Private Sub FormBrowser_Load(sender As Object, e As EventArgs) Handles Me.Load

        Dim cfsettings As New CefSettings With {
            .UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
            .Locale = "ko-KR"}
        Cef.Initialize(cfsettings)

        BrowserMain = New CefSharp.WinForms.ChromiumWebBrowser(TextURL.Text) With {.Dock = DockStyle.None, .Visible = False}
        Me.Controls.Add(BrowserMain)
        Call Resize_Browser()
        BrowserMain.Visible = True

        Call ControlSetting()
        HomePage = TextURL.Text

        Randomize()
    End Sub

    Private Sub FormBrowser_Resize(sender As Object, e As EventArgs) Handles Me.Resize
        ButtonNavigate.Left = Me.Width - ButtonNavigate.Width
        TextURL.Width = ButtonNavigate.Left
        If BrowserMain IsNot Nothing Then Call Resize_Browser()
    End Sub

    Private Sub TextURL_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextURL.KeyPress
        If e.KeyChar = vbCr Then
            BrowserMain.LoadUrl(TextURL.Text)
        End If
    End Sub

    Private Sub ButtonNavigate_Click(sender As Object, e As EventArgs) Handles ButtonNavigate.Click
        BrowserMain.LoadUrl(TextURL.Text)
    End Sub

    Private Sub Resize_Browser()
        BrowserMain.Top = TextURL.Top + TextURL.Height
        BrowserMain.Width = Me.Width
        BrowserMain.Height = Me.Height - TextURL.Top - TextURL.Height
    End Sub

    Private Sub ButtonBack_Click(sender As Object, e As EventArgs) Handles ButtonBack.Click
        BrowserMain.Back
    End Sub

    Private Sub ButtonForward_Click(sender As Object, e As EventArgs) Handles ButtonForward.Click
        BrowserMain.Forward
    End Sub

    Private Sub ButtonReload_Click(sender As Object, e As EventArgs) Handles ButtonReload.Click
        BrowserMain.Reload
    End Sub

    Private Sub ButtonHome_Click(sender As Object, e As EventArgs) Handles ButtonHome.Click
        BrowserMain.LoadUrl(HomePage)
    End Sub

    Private Sub BrowserMain_FrameLoadEnd(sender As Object, e As FrameLoadEndEventArgs) Handles BrowserMain.FrameLoadEnd
        If e.Frame.IsMain Then
            BrowserMain.GetSourceAsync().ContinueWith(Sub()
                                                          Dim d As ControlCallBack = New ControlCallBack(AddressOf ControlSetting)
                                                          Me.Invoke(d)
                                                      End Sub)
        End If
    End Sub

    Private Sub ControlSetting()
        TextURL.Text = BrowserMain.Address
        ButtonBack.Enabled = BrowserMain.CanGoBack
        ButtonForward.Enabled = BrowserMain.CanGoForward
    End Sub

End Class


위 소스대로 만든 후 실행시 아래와 같은 화면이 나오면 성공

TBrowser 실행화면

위 화면에서 Back, Forward가 Disable 상태로 되어있는걸 확인하자.


이전 강좌에 추가되거나 변경된 부분만 살펴보도록 하자.

Line 5 : Private Delegate Sub ControlCallBack()

요고 아주 재밌는게 하나 나왔다. Delegate 지정자를 사용해서 콜백함수를 하나 선언했는데 Delegate 관련 자세한 내용은 추후 살펴보기로 하고, 여기서는 브라우저의 이벤트에서 직접 폼의 컨트롤을 다룰때 발생하는 크로스 스레드 오류를 해결하기 위해 사용한다는 정도로만 알아두자.

Line 6 : Private HomePage As String

Home 버튼 클릭시 가야할 홈페이지로 사용하기 위해 변수를 하나 추가했고, FormLoad에서 TextURL.Text로 값을 입력했다.

프로그램 흐름상 브라우저 로딩이 완료되는 순간에 실행되는 ControlSetting 함수에 대해 먼저 알아보자.

TextURL.Text = BrowserMain.Address

브라우저는 항상 주소를 입력하는게 아니고 페이지내 링크를 클릭해서 이동하는 경우가 더 많으니 브라우저의 주소가 변경될때마다 주소창을 업데이트 해주어야 한다.

ButtonBack.Enabled = BrowserMain.CanGoBack
ButtonForward.Enabled = BrowserMain.CanGoForward

개인적으로 ChromiumWebBrowser 컨트롤이 지원하는 기능중 가장 마음에 드는 기능중 하나이다. CanGoBack, CanGoForward 뒤로 갈데가 있느냐? 앞으로 갈데가 있느냐? 는 의미인데 이번 예제처럼 브라우저 로딩완료시 값을 읽어와서 Back, Forward 버튼을 활성화/비활성화 시키는 용도로 사용된다.
Form_Load시에도 한번 호출해서 버튼 활성화 여부를 결정지어줬다. 그 결과 갈 수 있는 방향으로만 버튼이 활성화되게 된다.

이번에는 위 함수를 호출하는 BrowserMain_FrameLoadEnd 이벤트에 대해서 알아보자. 브라우저 로딩 완료시 실행되는 이벤트로 보통 페이지 소스를 읽어오거나, 이번 예제처럼 버튼등 화면 컨트롤을 설정하는 용도로 사용된다.

여기서 직접 ControlSetting 함수를 호출하면 크로스 스레드 오류가 나온다. 폼에 사용되는 컨트롤은 자체 스레드로 동작하기 때문에 다른 스레드에서 사용할 수 없기 때문에 발생하는 오류이다. 그래서 콜백함수를 선언하고 Invoke로 만들어서 이 오류를 피해가는 것이다. Delegate와 한쌍으로 동작하며 함수포인터로 호출한다고 생각하면 될 듯 하다.

나머지 버튼클릭 이벤트는 그냥 보고 사용하면 될 정도의 수준이니 따로 설명하지는 않겠다.

반응형