AfxNova progress

Started by José Roca, November 14, 2025, 11:37:56 PM

Previous topic - Next topic

Paul Squires

Hi José,

I have gotten back to updating Tiko code and am just about ready to post the version 1.3.1 update. I can grab your most recent AfxNova repository files now, or I can wait a bit longer if you'd like to add anything before I publish the Tiko update. Just let me know.

Thanks,
Paul
Paul Squires
PlanetSquires Software

José Roca

Hi Paul,

Everything I have uploaded is working fine as far as I know, so there is no need to delay the release of the new version of Tiko.

As you can see, I'm working to provide access to the latest technologies, such as WebView2 and Direct2D. Direct2D, DirectWrite, and WIC can already be used if you manage the object lifetimes yourself and call the methods directly. I'm currently working on wrapper classes to make them easier to use by providing constructors, automatic memory management, and overloaded methods.

I have already finished wrapping the most important interfaces, but wrapping the entire set will take time, since Direct2D is a whole ecosystem. The advantages of Direct2D are that it is faster, offers higher quality, and is fully DPI‑aware — all essential qualities for modern 4K displays.

Paul Squires

Excellent, thanks! I will use your latest repository files. Very exciting new code you're working on! I look forward to using it when you are finished. AfxNova makes coding in FB so much easier and these new technologies will make it even better.
Paul Squires
PlanetSquires Software

José Roca

My next step will be to take full advantage of the WebView2 control and turn it into a true "super control".
 
I'm planning to write a canvas class that allows drawing anything you need: graphics, images, text, shapes, and more. The idea is to expose a classic, easy‑to‑use API on the outside, while internally generating the required HTML, CSS, and JavaScript to perform the rendering.

This approach will make it possible to build all kinds of document‑related features:

- invoices and reports
- barcodes and QR codes
- embedded images
- tables and layouts
- previews and printouts
- charts and visualizations
- even animations

Basically, anything you can do on a modern web page will be available through a simple, traditional API.


The WebView2 control also has a localized context menu and/or shortcuts that allow to save, copy, rotate images, zoom and printing.

José Roca

Mi idea is working.

I'm currently developing a new graphics engine based on Microsoft WebView2, wrapped inside a custom class that exposes a clean and easy‑to‑use API.

The goal is simple: give you a powerful 2D drawing system without requiring you to learn HTML, CSS, or JavaScript

Under the hood, the engine uses an HTML5 <canvas> element and JavaScript to perform all rendering. This means you automatically benefit from:


- GPU‑accelerated drawing
- smooth rendering with no flicker
- high‑resolution text and shapes
- automatic scrolling when the canvas is larger than the control
- modern browser‑level performance

But you never have to deal with any of that complexity.

Instead, you work with a very simple and intuitive API, for example:

pCanvas->DrawText("Hello World", 100, 100, "red", 40)
pCanvas->DrawLine(50, 50, 300, 200, "blue", 4)
pCanvas->DrawCircle(200, 200, 50, "purple", 3)

No fonts to create.
No pens or brushes.
No device contexts.
No GDI or Direct2D setup.
Just straightforward drawing commands.

If you do know HTML, CSS, or JavaScript, you can extend the system even further. But if you don't, the API will give you what you need to draw text, shapes, images, and more.

In short, this project aims to provide a modern, lightweight, and extremely easy graphics language, built on top of WebView2 but completely hiding the web technologies behind a clean and friendly interface.

Johan Klassen

Good day José Roca  :)
this is great stuff, I can see that creating a GUI applications using your WebView2 class will be easy, even for me, thank you ;D

Paul Squires

Reminds me a lot of the Tauri project and what they've accomplished as an alternative to Electron.
https://v2.tauri.app/

Tauri is cross platform and written in Rust.
Paul Squires
PlanetSquires Software

José Roca

#37
The idea is simple. I already have a class, CWebView2, to allow to embed an instance of WebView2 in any window. CWebView2Canvas extends CWebView2, calls the BASE constructor to create the instance of WebView2 and...

Uses this tiny html script to create a canvas:


  DIM s AS STRING = $"<html>"
  s += "<body style='margin:0; padding:0; overflow:auto;'>"
  s += $"<canvas id='cv' width='" & STR(cvWidth) & "' height='" & STR(cvHeight) & "'></canvas>"
  s += $"</body>"
  s += $"</html>"

Uses this tiny JavaScript function to get the context when the web page is loaded:

  DIM JS_INIT AS STRING = $"var cv, ctx;"
  JS_INIT += "window.onload = function() {"
  JS_INIT += "    cv = document.getElementById('cv');"
  JS_INIT += "    ctx = cv.getContext('2d');"
  JS_INIT += "};"

If the WebView2 control is ready, adds the script to the control and navigats to our tiny web page.

  IF this.IsReady THEN
      this.AddScriptToExecuteOnDocumentCreated(JS_INIT, NULL)
      this.NavigateToString(s)
  END IF

With the reference to CWebView2Canvas class we can call our wrapper functions, e.g.

DIM pCanvas AS CWebView2Canvas = CWebView2Canvas(hWin, dwsUserDataFolder)
...
...
pCanvas->DrawText("Hello World", 100, 100, "red", 40)
pCanvas->DrawLine(50, 50, 300, 200, "blue", 4)
pCanvas->DrawCircle(200, 200, 50, "purple", 3)

As WebView2 is asynchronous, the safest way is to use the CWebView2NavigationCompletedEventHandler. I provide overridable classes to implement your custom event handlers.

For the wrapper methods, I use JavaScript inside them, e.g.

' ========================================================================================
' Draws a circle.
' x, y : coordinates
' radius; Radius
' clr: The color of the pen
' nWidth : The width of the pen
' ========================================================================================
PRIVATE SUB CWebView2Canvas.DrawCircle( _
        BYVAL x AS SINGLE, BYVAL y AS SINGLE, _
        BYVAL radius AS SINGLE, _
        BYREF clr AS STRING, _
        BYVAL nWidth AS LONG = 1)

  ' // Make sure that the JS function exists
  IF m_hasDrawCircle = FALSE THEN
      DIM js AS STRING
      js = _
      "function drawCircle(x, y, radius, color, width) {" _
      & " ctx.strokeStyle = color;" _
      & " ctx.lineWidth = width;" _
      & " ctx.beginPath();" _
      & " ctx.arc(x, y, radius, 0, Math.PI * 2);" _
      & " ctx.stroke();" _
      & "}"
      this.ExecuteScript(js, NULL)
      m_hasDrawCircle = TRUE
    END IF

  ' // Call the JS function
  DIM js AS STRING
  js = "drawCircle(" _
      & STR(x) & "," & STR(y) & "," _
      & STR(radius) & ",'" _
      & clr & "'," & STR(nWidth) & ");"

  this.ExecuteScript(js, NULL)

END SUB
' ========================================================================================

If the JavaScript function does not exist, the wrapper adds it to the web page and then calls it with ExecuteScript.

As I still don't have much expertise with JavaScript, I ask the IA to write it for me.

It is not crossplatform, because WebView2 is a control for Windows, but the size of the executable of one small example with a CWindow's GUI, the CWebView2 and CWebView2Canvas classes, the event's class, DWSTRING and the wrappers for AfxNova, weights around 67 KB, not 600. As a simple example of CWindow with a button, weights 54.5 KB, this means that my WebView2 classes add 12.5 KB.

As the javascript functions are added on demand, the size of the application will grow depending on how many different ones you use. The size of the executable of the example that produces the capture below weights 82.5 KB and it is using 14 different functions.

We are not limited to graphics functions, but we can do everything: images, video, audio... and  even to use external libraries.



José Roca

#38
The embeded WebView2 control also has contextual localized menus that allow to save or copy the image, and shortcut keys. For example, you can zoom the image with Ctrl+/-, or using Ctrl and the mouswheel. Scrollbars are added automatically if needed. And Ctrl+P activates the browser printer dalog, so we have printing and print preview for free. We can generate PDF files if we choose a driver like Microsoft Print to PDF or any other that you prefer.

We can also drop images, pdf files and other objects in the control.

José Roca

I have added methods to draw text that can also be used with effects to, for example, draw logos.