ObjReader Community

SDK programming => Canary Bay => Topic started by: Patrice Terrier on March 21, 2021, 02:27:06 pm

Title: PowerBASIC Barebone version
Post by: Patrice Terrier on March 21, 2021, 02:27:06 pm
This is a simplified version of CanaryBay, without bells and whistles.

The purpose of this code is to help you understand what is going on...

The CanaryBay project is a compound application mixing the core WV2B binary EXE (written in C++) within a host application that could be written with any programming language.

Compound application is using interprocess to communicate together via a specific registered message:
gP.WM_BROWSER = RegisterWindowMessage("WM_BROWSER") '// Send/Get messages to/from the Browser

The inital parameters are shared using a config file (szConfig) to setup the WV2B behavior when firing the browser.
Code: [Select]
type SETBIN
    dwExStyle as dword
    dwStyle as dword
    hParent as dword
    x as long
    y as long
    w as long
    h as long
    onTABclose as WSTRING * %MAX_PATH
    defaultURL as WSTRING * %MAX_PATH
end type
The names of the SETBIN structure are self explanatory, and are used to setup the CreateWindowEx of the main Browser window.

Use of region SetBrowserRegion
creates a hole region within the host window to display WV2B runing like a child process.

The host application can listen WV2B messages from the ProcessBrowserMessage subroutine.
For now WM_NCDESTROY is sent when the last Browser TAB is closing.

Firing the browser is done with buttons using the WM_COMMAND message from the standard Wndproc
Code: [Select]
    case %WM_COMMAND:
         local wP as long
         wP = LOINT(wParam)
         select case long wP
         case %IDC_BTN1
              StartBrowser("https://forum.powerbasic.com/")
              function = 0: exit function
         case %IDC_BTN2
              StartBrowser("http://www.objreader.com/download/video/TobVerF6zgr_576.mp4")
              function = 0: exit function
         case %IDC_EXIT
              if gP.hBrowser then SendMessage(gP.hBrowser, %WM_CLOSE, 0, 0)
              DestroyWindow(hWnd)
              function = 0: exit function
         end select
StartBrowser being the master API to fire WV2B.

The "PowerBASIC" button is firing a standard website.
The "D3D video" button is firing a video, just to show you that WV2B itself being a "Direct 3D" application, is using the latest web technology.
The "Exit" button is meant to shut down the whole compound application.

The main window of the host application is a bare one, using only
%WS_POPUP or %WS_CLIPCHILDREN or %WS_CLIPSIBLINGS.
This means no caption, no border, nothing related to the NonClient_AREA, thus freeing us of the Windows default interactions.
However the standard behavior of a caption bar is emulated to move the window around, and changing the caption color to figure the gain or lost of focus.

About the coding style:
It is using the core SDK syntax API, that is the only way to write portable code, because the core API is the common denominator understood by all Windows languages.

Contribution:
If you appreciate this code, please consider to make a donation (http://www.objreader.com/index.php?topic=325.0) to support my work.

Screenshot:

(http://www.objreader.com/download/images/BBC.jpg)
(BTW, this is a custom 3D model running in my ObjReader 3D engine, and available in the "car" collection for free)

If you have questions about this code, feel free to post them here.
Title: Re: PowerBASIC Barebone version
Post by: Patrice Terrier on March 22, 2021, 03:04:32 pm
I did a mistake while cleaning the code, the part shown in red below must be kept

sub StartBrowser(sURL as string)
    '// if the Browser is already running, then shut it down in order to create a brand new page
    if (IsWindow(gP.hBrowser)) then
        SendMessage(gP.hBrowser, %WM_CLOSE, 0, 0)
        gP.hBrowser = 0
    end if

    local fname as string: fname = "WV2B"
    local szConfig as asciiz * %MAX_PATH: szConfig = fTempPath() + fname + ".bin"

    '// Customize the Browser size
    local cfg as SETBIN, x, y, w, h as long
    BrowserLocation(x, y, w, h)

    cfg.dwExStyle = %WS_EX_TOOLWINDOW '// Don't show the Browser icon on the taskbar
    cfg.dwStyle = %WS_POPUP or %WS_VISIBLE
    cfg.hParent = gP.hMain
    cfg.x = x
    cfg.y = y
    cfg.w = w
    cfg.h = h
    cfg.onTABclose = "https://unsplash.it/1962/1080?random"
    cfg.defaultURL = "https://www.google.fr/"
    '// Create the config file
    local fHandle as long
    fHandle = CreateFile(szConfig, %GENERIC_WRITE, 0, byval %NULL, %CREATE_ALWAYS, %FILE_ATTRIBUTE_NORMAL, byval %NULL)
    if (fHandle <> -1) then
        local BytesWritten as long
        WriteFile(fHandle, byval varptr(cfg), sizeof(cfg), BytesWritten, byval %NULL)
        CloseHandle(fHandle)
    end if

    '// Fire the Browser
    local hWnd as dword
    hWnd = CreateBrowserProcess(ExePath() + fname + ".exe", sURL)

    if (hWnd) then ' 03-22/2021 this code was put in REM in Barebone, that is an error it should be kept.
        local hCtrl as dword
        hCtrl = GetDlgItem(gP.hMain, %IDC_BROWER_CONTAINER)
        if (IsWindowVisible(hCtrl)) then ShowWindow(hCtrl, %SW_HIDE)
        ResizeWindow(hWnd)
        gP.hBrowser = hWnd
    end if

end sub



I have also added a new ProcessBrowserMessage, to display the name of the URL entered by the user in the navigate field.

'// This is the place to handle the messages sent by the browser (search for gP.WM_BROWSER in WndProc)
sub ProcessBrowserMessage(byval wParam as dword, byval lParam as long)
    if wParam = %WM_NCDESTROY then '// Last Browser TAB is closing
        if gP.hRgn then
            DeleteObject(gP.hRgn): gP.hRgn = 0
            SetWindowRgn(gP.hMain, gP.hRgn, %False)
'            if (IsWindowVisible(GetDlgItem(gP.hMain, %IDC_UNDOCK))) then
'                local r as rect, p as POINT
'                GetWindowRect(GetDlgItem(gP.hMain, %IDC_BROWER_CONTAINER), r)
'                p.x = r.nLeft: p.y = r.nTop: ScreenToClient(gP.hMain, p)
'                MoveWindow(GetDlgItem(gP.hMain, %IDC_BROWER_CONTAINER), p.x, p.y + gP.dock_offset, rWidth(r), rHeight(r) - gP.dock_offset, %TRUE)
'            end if
            ShowWindow(GetDlgItem(gP.hMain, %IDC_BROWER_CONTAINER), %SW_SHOW)
'            ShowWindow(GetDlgItem(gP.hMain, %IDC_UNDOCK), %SW_HIDE)
'            ShowWindow(GetDlgItem(gP.hMain, %IDC_DOCK), %SW_HIDE)

            SetForeGroundWindow(gP.hMain)

            WindowRedraw(gP.hMain)
        end if
    elseif wParam = %WM_SETTEXT then
        local szText AS ASCIIZ * %MAX_PATH
        local Length AS LONG
        Length = GetWindowText(GetDlgItem(gP.hMain, %IDC_BROWER_CONTAINER), szText, SIZEOF(szText))
        if Length then zTrace(szText)
    end if
end sub



Title: Re: PowerBASIC Barebone version
Post by: Carlo Pagani on June 06, 2021, 11:41:38 am
Thanks Patrice, this is great stuff to experiment with browser app. I am playing around with OAuth2 so I have a question if the browser URL input can be disabled or hidden via a message?
Title: Re: PowerBASIC Barebone version
Post by: Patrice Terrier on June 06, 2021, 07:43:29 pm
Carlo

With the latest WV2B 64-bit (http://www.objreader.com/index.php?topic=351.0).

You can use something like this WinDev code in the ProcessBrowserMessage callback procedure(see the code in red)

sub ProcessBrowserMessage(byval wParam as dword, byval lParam as long)
    if wParam = %WM_NCDESTROY then '// Last Browser TAB is closing
        if gP.hRgn then
            DeleteObject(gP.hRgn): gP.hRgn = 0
            SetWindowRgn(gP.hMain, gP.hRgn, %False)
            if (IsWindowVisible(GetDlgItem(gP.hMain, %IDC_UNDOCK))) then
                local r as rect, p as POINT
                GetWindowRect(GetDlgItem(gP.hMain, %IDC_BROWER_CONTAINER), r)
                p.x = r.nLeft: p.y = r.nTop: ScreenToClient(gP.hMain, p)
                MoveWindow(GetDlgItem(gP.hMain, %IDC_BROWER_CONTAINER), p.x, p.y + gP.dock_offset, rWidth(r), rHeight(r) - gP.dock_offset, %TRUE)
            end if
            ShowWindow(GetDlgItem(gP.hMain, %IDC_BROWER_CONTAINER), %SW_SHOW)
            ShowWindow(GetDlgItem(gP.hMain, %IDC_UNDOCK), %SW_HIDE)
            ShowWindow(GetDlgItem(gP.hMain, %IDC_DOCK), %SW_HIDE)

            SetForeGroundWindow(gP.hMain)

            WindowRedraw(gP.hMain)
        end if
    elseif wParam = %WM_SETTEXT then
        local hMapFile, pBuf as dword
        hMapFile = OpenFileMapping(%FILE_MAP_ALL_ACCESS, %false, "WV2B_MF")
        if (hMapFile) then
            pBuf = MapViewOfFile(hMapFile, %FILE_MAP_ALL_ACCESS, 0, 0, %BUF_SIZE)
            if (pBuf) then
                local sAnsi as string
                local CharCount as dword
                CharCount = LStrlenW(BYVAL pBuf) '// Get dual bytes character count
                sAnsi     = NUL$(CharCount)      '// Initialize string
                WideCharToMultiByte(%CP_ACP, 0, byval pBuf, CharCount, byval strptr(sAnsi), CharCount, byval 0, byval 0)

                zTrace((sAnsi)) '// Display the URL entered by the user

             '// To refuse the entered URL (parental control by example)
             '// use %MG_CANCEL below
             'SendMessageA(gP.hBrowser, gP.WM_BROWSER, %MG_CANCEL, 0)

                UnmapViewOfFile(pBuf)
            end if
            CloseHandle(hMapFile)
        end if
    end if
end sub


Title: Re: PowerBASIC Barebone version
Post by: Carlo Pagani on June 06, 2021, 08:08:48 pm
Thanks Patrice - I will play now with this and see the possibilities. I quite like the way you overlay the browser window into the 32Bit app.

--Edit FYI
There are some issues on my machine (Win 10 x64) in that the icons don't load the page and if I type in a URL, I get a transparent window where the browser was?
Title: Re: PowerBASIC Barebone version
Post by: Patrice Terrier on June 07, 2021, 10:28:16 am
Carlo

Are you able to reproduce this behavior systematically?

If yes, tell me step by step what you are doing.