Webview2 control - Chromium browser for Purebasic (Windows) [Jan 1, 2024]

Everything else that doesn't fall into one of the other PB categories.
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Webview2 control - Chromium browser for Purebasic (Windo

Post by Justin »

I don't think is CEF based, it's MS implementation of the Chromium browser (MS Edge) as a COM Control, it is supossed to be easier to implement in C / C++ , .NET , C# , WPF than CEF, there are also Linux and Mac versions planned.
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Webview2 control - Chromium browser for Purebasic (Windo

Post by Lunasole »

Justin wrote: Mon Apr 12, 2021 8:57 pm I don't think is CEF based, it's MS implementation of the Chromium browser (MS Edge) as a COM Control, it is supossed to be easier to implement in C / C++ , .NET , C# , WPF than CEF, there are also Linux and Mac versions planned.
Thanks for some brief view
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
Morty
User
User
Posts: 35
Joined: Mon Mar 19, 2007 8:30 am
Location: Germany
Contact:

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by Morty »

Thank you. This is awesome!

So far it works very well, but I have a big problem to place it into ContainerGadgets

I will put the WebViewControll in a Container as part of a SplitGadget in a Container. The initialization is ok, no errors, but the view isn't shown. I've tried with SetParent_ and other boundries, but it doesn't work (is not shown). To get it clear - If I put it on a single window it works as expected.

Code: Select all

ContaingerGadget1
	ListGadget
	ContainerGadget2
		CanvasGadget
		WebView2Controll
	[SpinGadget: ListGadget & ContainerGadget2]
Thanks
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by Justin »

Hi Morty,

Are you setting the container gadget that will host the webview in the Environment_Created event?
It should be something like this, taken from the basic_browser_async.pb example:

Code: Select all

Procedure wvEnvironment_Created(*this.WV2_EVENT_HANDLER, result.l, environment.ICoreWebView2Environment)	
	If result = #S_OK
		environment\QueryInterface(?IID_ICoreWebView2Environment, @app\wvEnvironment)
		;SET CONTAINER GADGET THAT WILL HOST WEBVIEW
		app\wvEnvironment\CreateCoreWebView2Controller(GadgetID(YOUR_GADGET_CONTAINER), wv2_EventHandler_New(?IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler, @wvController_Created()))

		wv2_EventHandler_Release(*this)
		app\wvEnvironment\Release()

	Else
		MessageRequester("Error", "Failed to create WebView2Environment.")
		End 
	EndIf 
EndProcedure
Then you will need to resize the webview to the container dimension in wvController_Created event and everytime the container is resized.
I will test it by myself later.
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by Justin »

I think this code does it i need to check it with more dpi settings with another computer at home, i will update the repository later.

Edit: Fixed dpi scaling

Code: Select all

;container.pb

IncludeFile "..\PBWebView2.pb"

EnableExplicit

;- APP_TAG
Structure APP_TAG
	window.i
	splitter.i
	cont1.i
	cont2.i
	listGd.i
	canvas.i
	wvEnvironment.ICoreWebView2Environment
	wvController.ICoreWebView2Controller
	wvCore.ICoreWebView2
	*eventNavigationCompleted.WV2_EVENT_HANDLER
	*eventNavigationSarting.WV2_EVENT_HANDLER
EndStructure
Global.APP_TAG app

;- DECLARES
Declare main()

Declare window_Close()
Declare window_Resize()
Declare wv_Resize()
Declare window_ProcessEvents(ev.l)

Declare wvEnvironment_Created(*this.WV2_EVENT_HANDLER, result.l, environment.ICoreWebView2Environment)	
Declare wvController_Created(*this.WV2_EVENT_HANDLER, result.l, controller.ICoreWebView2Controller)
Declare wv_NavigationCompleted(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2NavigationCompletedEventArgs)
Declare wv_NavigationStarting(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2NavigationStartingEventArgs)

Procedure window_Proc(hwnd.i, msg.l, wparam.i, lparam.i)
	Select msg
		Case #WM_MOVE, #WM_MOVING
			wv2_Controller_On_WM_MOVE_MOVING(app\wvController)
	EndSelect
	
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure wvEnvironment_Created(*this.WV2_EVENT_HANDLER, result.l, environment.ICoreWebView2Environment)	
	If result = #S_OK
		environment\QueryInterface(?IID_ICoreWebView2Environment, @app\wvEnvironment)
		app\wvEnvironment\CreateCoreWebView2Controller(GadgetID(app\cont2), wv2_EventHandler_New(?IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler, @wvController_Created()))

		wv2_EventHandler_Release(*this)
		app\wvEnvironment\Release()

	Else
		MessageRequester("Error", "Failed to create WebView2Environment.")
		End 
	EndIf 
EndProcedure

Procedure wvController_Created(*this.WV2_EVENT_HANDLER, result.l, controller.ICoreWebView2Controller)	
	If result = #S_OK
		controller\QueryInterface(?IID_ICoreWebView2Controller, @app\wvController)
		app\wvController\get_CoreWebView2(@app\wvCore)
		
		;Setup events
		app\eventNavigationCompleted = wv2_EventHandler_New(?IID_ICoreWebView2NavigationCompletedEventHandler, @wv_NavigationCompleted())
		app\wvCore\add_NavigationCompleted(app\eventNavigationCompleted, #Null)
		
		app\eventNavigationSarting = wv2_EventHandler_New(?IID_ICoreWebView2NavigationStartingEventHandler, @wv_NavigationStarting())
		app\wvCore\add_NavigationStarting(app\eventNavigationSarting, #Null)
		
		window_Resize()
		wv_Resize()
		
		app\wvCore\Navigate("https://duckduckgo.com")

		wv2_EventHandler_Release(*this)

	Else
		MessageRequester("Error", "Failed to create WebView2Controller.")
		End
	EndIf 
EndProcedure

Procedure wv_NavigationCompleted(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2NavigationCompletedEventArgs)
	Debug "Event NavigationCompleted"

EndProcedure

Procedure wv_NavigationStarting(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2NavigationStartingEventArgs)
	Protected.i uri
	Protected.s suri
	
	Debug "Event NavigationStarting"

	If args\get_uri(@uri) = #S_OK
		suri = PeekS(uri)
		CoTaskMemFree_(uri)

		;CANCEL NAVIGATION
		If LCase(StringField(GetURLPart(suri, #PB_URL_Site), 2, ".")) = "google"
			MessageRequester("Purebasic", "Sorry google is banned.")
			args\put_Cancel(#True)
		EndIf 
	EndIf 
EndProcedure

Procedure window_Close()
	If app\wvController
		app\wvController\Close()
		app\wvController\Release()	
	EndIf 
	
	If app\wvCore : app\wvCore\Release() : EndIf 
	
	If app\eventNavigationCompleted
		wv2_EventHandler_Release(app\eventNavigationCompleted)
	EndIf 
	
	If app\eventNavigationSarting
		wv2_EventHandler_Release(app\eventNavigationSarting)
	EndIf 
	
	ProcedureReturn #True ;Exit message loop.
EndProcedure

Procedure canvas_Draw()
	If StartDrawing(CanvasOutput(app\canvas))
		Circle(10, 10, 10, RGB(255, 0, 0))
		StopDrawing()
 	EndIf 
EndProcedure

Procedure window_Resize()		
	ResizeGadget(app\cont1, 0, 0, WindowWidth(app\window), WindowHeight(app\window))
EndProcedure

Procedure cont1_Resize()
	ResizeGadget(app\splitter, 0, 0, GadgetWidth(app\cont1), GadgetHeight(app\cont1))
EndProcedure

Procedure wv_Resize()
	Protected.RECT wvBounds

	wvBounds\left = DesktopScaledX(GadgetWidth(app\canvas))
	wvBounds\top = 0
	wvBounds\bottom = DesktopScaledY(GadgetHeight(app\cont2))
	wvBounds\right = DesktopScaledX(GadgetWidth(app\cont2))
	If app\wvController
		wv2_Controller_put_Bounds(app\wvController, @wvBounds)
	EndIf 
EndProcedure

Procedure cont2_Resize()

	ResizeGadget(app\canvas, 0, 0, #PB_Ignore, GadgetHeight(app\cont2))
	canvas_Draw()
	
	wv_Resize()
EndProcedure

Procedure window_ProcessEvents(ev.l)
	Select ev
		Case #PB_Event_CloseWindow : ProcedureReturn window_Close()
	EndSelect
	
	ProcedureReturn #False 
EndProcedure

Procedure main()
	Protected.l winWidth, winHeight, x
	
	If wv2_GetBrowserVersion("") = ""
		MessageRequester("Error", "MS Edge not found, install MS Edge runtime.")
		End 
	EndIf
	
	winWidth = 600
	winHeight = 400
	
	app\window = OpenWindow(#PB_Any, 10, 10, winWidth, winHeight, "PBWebView2 - Basic Browser Asynchronous Creation", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
	SetWindowCallback(@window_Proc(), app\window)
	
	app\cont1 = ContainerGadget(#PB_Any, 0, 0, WindowWidth(app\window), WindowHeight(app\window))
	BindGadgetEvent(app\cont1, @cont1_Resize(), #PB_EventType_Resize)
	app\listGd = ListViewGadget(#PB_Any, 0, 0, 0, 0)
	For X = 1 To 10
  	AddGadgetItem (app\listGd, -1, "Item" + Str(x))
  Next

	app\cont2 = ContainerGadget(#PB_Any, 0, 0, 0, 0)
	BindGadgetEvent(app\cont2, @cont2_Resize(), #PB_EventType_Resize)
	app\canvas = CanvasGadget(#PB_Any, 0, 0, 0, 0)
	CloseGadgetList()
	app\splitter = SplitterGadget(#PB_Any, 0, 0, 600, 400, app\listGd, app\cont2, #PB_Splitter_Separator   )
	CloseGadgetList()
	
	ResizeGadget(app\canvas, 0, 0, GadgetWidth(app\cont2) / 2, GadgetHeight(app\cont2))
	
	canvas_Draw()

	BindEvent(#PB_Event_SizeWindow, @window_Resize())
	CreateCoreWebView2EnvironmentWithOptions("", "", #Null, wv2_EventHandler_New(?IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, @wvEnvironment_Created()))

	Repeat
	Until window_ProcessEvents(WaitWindowEvent()) = #True 
EndProcedure

main()
Morty
User
User
Posts: 35
Joined: Mon Mar 19, 2007 8:30 am
Location: Germany
Contact:

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by Morty »

Hi Justin,

thank you very much. That was realy fast. I will give it a try in the next days.

Morty
fluent
User
User
Posts: 68
Joined: Sun Jan 24, 2021 10:57 am

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by fluent »

Another question that is bothering me a little (although not important)... Would there be a way to add a custom HTTP header to each request (for both top navigation and resource loading events)? So that each request has a custom "HeaderX:ValueY" header?
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by Justin »

Hi fluent,

You can set custom headers handling the WebResourceRequested event, i have updated the basic_browser_async.pb example with that, not in the repository yet, look at the wv_WebResourceRequested() procedure.
You can check your headers online at:
https://headers.cloxy.net/request.php
You have to set a request filter for the requests you want to handle with core\AddWebResourceRequestedFilter() done in wvController_Created().
basic_browser_async.pb

Code: Select all

;basic_browser_async.pb

;Basic browser asyncrhonous creation.

IncludeFile "..\PBWebView2.pb"

EnableExplicit

;- APP_TAG
Structure APP_TAG
	window.i
	wvEnvironment.ICoreWebView2Environment
	wvController.ICoreWebView2Controller
	wvCore.ICoreWebView2
	*eventNavigationCompleted.WV2_EVENT_HANDLER
	*eventNavigationSarting.WV2_EVENT_HANDLER
	*eventWebResourceRequested.WV2_EVENT_HANDLER
EndStructure
Global.APP_TAG app

;- DECLARES
Declare main()

Declare window_Close()
Declare window_Resize()
Declare window_ProcessEvents(ev.l)

Declare wvEnvironment_Created(*this.WV2_EVENT_HANDLER, result.l, environment.ICoreWebView2Environment)	
Declare wvController_Created(*this.WV2_EVENT_HANDLER, result.l, controller.ICoreWebView2Controller)
Declare wv_NavigationCompleted(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2NavigationCompletedEventArgs)
Declare wv_NavigationStarting(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2NavigationStartingEventArgs)
Declare wv_WebResourceRequested(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2WebResourceRequestedEventArgs)	

Procedure window_Proc(hwnd.i, msg.l, wparam.i, lparam.i)
	Select msg
		Case #WM_MOVE, #WM_MOVING
			wv2_Controller_On_WM_MOVE_MOVING(app\wvController)
	EndSelect
	
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure wvEnvironment_Created(*this.WV2_EVENT_HANDLER, result.l, environment.ICoreWebView2Environment)	
	If result = #S_OK
		environment\QueryInterface(?IID_ICoreWebView2Environment, @app\wvEnvironment)
		app\wvEnvironment\CreateCoreWebView2Controller(WindowID(app\window), wv2_EventHandler_New(?IID_ICoreWebView2CreateCoreWebView2ControllerCompletedHandler, @wvController_Created()))

		wv2_EventHandler_Release(*this)
		app\wvEnvironment\Release()

	Else
		MessageRequester("Error", "Failed to create WebView2Environment.")
		End 
	EndIf 
EndProcedure

Procedure wvController_Created(*this.WV2_EVENT_HANDLER, result.l, controller.ICoreWebView2Controller)	
	If result = #S_OK
		controller\QueryInterface(?IID_ICoreWebView2Controller, @app\wvController)
		app\wvController\get_CoreWebView2(@app\wvCore)
		
		;Setup events
		app\eventNavigationCompleted = wv2_EventHandler_New(?IID_ICoreWebView2NavigationCompletedEventHandler, @wv_NavigationCompleted())
		app\wvCore\add_NavigationCompleted(app\eventNavigationCompleted, #Null)
		
		app\eventNavigationSarting = wv2_EventHandler_New(?IID_ICoreWebView2NavigationStartingEventHandler, @wv_NavigationStarting())
		app\wvCore\add_NavigationStarting(app\eventNavigationSarting, #Null)
		
		app\wvCore\AddWebResourceRequestedFilter("*", #COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL)
		app\eventWebResourceRequested = wv2_EventHandler_New(?IID_ICoreWebView2WebResourceRequestedEventHandler, @wv_WebResourceRequested())
		app\wvCore\add_WebResourceRequested(app\eventWebResourceRequested, #Null)
		
		
		window_Resize()
		
		app\wvCore\Navigate("https://duckduckgo.com")

		wv2_EventHandler_Release(*this)

	Else
		MessageRequester("Error", "Failed to create WebView2Controller.")
		End
	EndIf 
EndProcedure

Procedure wv_WebResourceRequested(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2WebResourceRequestedEventArgs)	
	Protected.ICoreWebView2WebResourceRequest req
	Protected.ICoreWebView2HttpRequestHeaders reqHeaders
	
	;SET CUSTOM HEADER
	If args\get_Request(@req) = #S_OK
		If req\get_Headers(@reqHeaders) = #S_OK
			reqHeaders\SetHeader("myheader", "myvalue")
			
			reqHeaders\Release()
		EndIf 
		
		req\Release()
	EndIf 
EndProcedure

Procedure wv_NavigationCompleted(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2NavigationCompletedEventArgs)
	Debug "Event NavigationCompleted"

EndProcedure

Procedure wv_NavigationStarting(*this.WV2_EVENT_HANDLER, sender.ICoreWebView2, args.ICoreWebView2NavigationStartingEventArgs)
	Protected.i uri
	Protected.s suri
	
	Debug "Event NavigationStarting"

	If args\get_uri(@uri) = #S_OK
		suri = PeekS(uri)
		CoTaskMemFree_(uri)

		;CANCEL NAVIGATION
		If LCase(StringField(GetURLPart(suri, #PB_URL_Site), 2, ".")) = "google"
			MessageRequester("Purebasic", "Sorry google is banned.")
			args\put_Cancel(#True)
		EndIf 
	EndIf 
EndProcedure

Procedure window_Close()
	If app\wvController
		app\wvController\Close()
		app\wvController\Release()	
	EndIf 
	
	If app\wvCore : app\wvCore\Release() : EndIf 
	
	If app\eventNavigationCompleted
		wv2_EventHandler_Release(app\eventNavigationCompleted)
	EndIf 
	
	If app\eventNavigationSarting
		wv2_EventHandler_Release(app\eventNavigationSarting)
	EndIf 
	
	If app\eventWebResourceRequested
		wv2_EventHandler_Release(app\eventWebResourceRequested)
	EndIf 
	
	ProcedureReturn #True ;Exit message loop.
EndProcedure

Procedure window_Resize()
	Protected.RECT wvBounds
		
	If app\wvController
		GetClientRect_(WindowID(app\window), @wvBounds)
		wv2_Controller_put_Bounds(app\wvController, @wvBounds)
	EndIf 
EndProcedure

Procedure window_ProcessEvents(ev.l)
	Select ev
		Case #PB_Event_CloseWindow : ProcedureReturn window_Close()
	EndSelect
	
	ProcedureReturn #False 
EndProcedure

Procedure main()	
	If wv2_GetBrowserVersion("") = ""
		MessageRequester("Error", "MS Edge not found, install MS Edge runtime.")
		End 
	EndIf
	
	app\window = OpenWindow(#PB_Any, 10, 10, 600, 400, "PBWebView2 - Basic Browser Asynchronous Creation", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
	SetWindowCallback(@window_Proc(), app\window)

	BindEvent(#PB_Event_SizeWindow, @window_Resize())
	
	CreateCoreWebView2EnvironmentWithOptions("", "", #Null, wv2_EventHandler_New(?IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, @wvEnvironment_Created()))

	Repeat
	Until window_ProcessEvents(WaitWindowEvent()) = #True 
EndProcedure

main()
fluent
User
User
Posts: 68
Joined: Sun Jan 24, 2021 10:57 am

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by fluent »

That's a fantastic example justin, thanks a lot.
firace
Addict
Addict
Posts: 899
Joined: Wed Nov 09, 2011 8:58 am

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by firace »

About memory usage you can pass Chromium flags when creating the control
https://peter.sh/experiments/chromium-c ... -switches/,
maybe disabling some things will help, i did it in the bootstrap.pb to disable web security, see main() proc.
Hello, a small question about the bootstrap.pb example:

It seems that the "--disable-web-security" additional argument has no effect here
(the example works fine, but if I check in the task manager, the additional argument doesn't seem to be passed to the msedgewebview2.exe process command line)

Any idea why? Could there be a bug in put_AdditionalBrowserArguments, or am I missing something?
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by Justin »

Hi firace,

the argument is passed here the first process has it, the command line is very long
Image

Using Windows 10 64.
Anyways i need to update it to the last SDK, i will take a closer look.
firace
Addict
Addict
Posts: 899
Joined: Wed Nov 09, 2011 8:58 am

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by firace »

Thanks Justin, I will do more testing on my end. Perhaps I've messed something up in the code.
User avatar
CELTIC88
Enthusiast
Enthusiast
Posts: 154
Joined: Thu Sep 17, 2015 3:39 pm

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by CELTIC88 »

great work.
interested in Cybersecurity..
User avatar
Derren
Enthusiast
Enthusiast
Posts: 313
Joined: Sat Jul 23, 2011 1:13 am
Location: Germany

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by Derren »

Hey,

this looks promising. Thanks for posting.

But now, over a year later, every machine (including mine) has Edge installed and the example codes still fail to run.
Does it still not work without the runtime or does the check in the code need an update?

---------------------------
Error
---------------------------
MS Edge not found, install MS Edge Runtime.
---------------------------
OK
---------------------------

Installed Edge info:
Microsoft Edge
Version 92.0.902.73 (Offizielles Build) (64-Bit)
Justin
Addict
Addict
Posts: 829
Joined: Sat Apr 26, 2003 2:49 pm

Re: Webview2 control - Chromium browser for Purebasic (Windows)

Post by Justin »

You still need to install the runtime or deploy it with your app (fixed runtime version).
https://developer.microsoft.com/en-us/m ... /webview2/
I don't think this will change, but who knows.

I need to update the code to the last sdk but the examples should work.
Post Reply