PlanetSquires Forums

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Problem: Modeless form and CWebCtx control  (Read 270 times)

Paul Squires

  • Administrator
  • Master Member
  • *****
  • Posts: 8635
  • Windows 10
    • PlanetSquires Software
Problem: Modeless form and CWebCtx control
« on: October 21, 2018, 11:09:58 PM »

Hi Jose, I have run into trouble trying to use the CWebCtx web browser control on a popup modeless CWindow form. I hope I am not not asking for too much but could you try modifying one of your sample programs to create and display the web browser control on a popup modeless form. My attempts have ended up with either a GPF or freezing of the application (and without displaying anything in the control. ie webpage or local static page).

Hope you can help  :-)
Thanks - Paul
Logged
Paul Squires
PlanetSquires Software
FireFly Visual Designer, WinFBE Editor

Josť Roca

  • Moderator
  • Master Member
  • *****
  • Posts: 3109
    • Jos
Re: Problem: Modeless form and CWebCtx control
« Reply #1 on: October 22, 2018, 10:01:10 AM »

This has been very hard. Is it an exam? :)

Code: [Select]
' ########################################################################################
' Microsoft Windows
' File: CW_ModelessPopupWindow.fbtpl
' Contents: Modeless popup window with embedded WebBrowser control
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2018 Josť Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

#define UNICODE
#include once "Afx/CWindow.inc"
#include once "Afx/CAxHost/CWebCtx.inc"
USING Afx

CONST IDC_POPUP = 1001
CONST IDC_WEBBROWSER = 1002

DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                          BYVAL hPrevInstance AS HINSTANCE, _
                          BYVAL szCmdLine AS ZSTRING PTR, _
                          BYVAL nCmdShow AS LONG) AS LONG

   END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)

' // Forward declarations
DECLARE FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
DECLARE FUNCTION PopupWindow (BYVAL hParent AS HWND) AS CWindow PTR
DECLARE FUNCTION PopupWndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                  BYVAL hPrevInstance AS HINSTANCE, _
                  BYVAL szCmdLine AS ZSTRING PTR, _
                  BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   AfxSetProcessDPIAware

   ' // Create the main window
   DIM pWindow AS CWindow
   DIM hWndMain AS HWND = pWindow.Create(NULL, "Modeless popup window with WebBrowser", @WndProc)
   pWindow.SetClientSize(900, 500)
   pWindow.Center

   ' // Add a button without position or size (it will be resized in the WM_SIZE message).
   pWindow.AddControl("Button", , IDC_POPUP, "&Popup")

   ' // Display the window
   ShowWindow(hWndMain, nCmdShow)
   UpdateWindow(hWndMain)

   ' // Dispatch Windows messages
   DIM uMsg AS MSG
   WHILE (GetMessageW(@uMsg, NULL, 0, 0) <> FALSE)
      ' // Check if a popup dialog is activated and get its handle
      DIM hFocusWnd AS HWND = GetParent(AfxGetControlHandle(GetFocus(), IDC_WEBBROWSER))
      ' // Otherwise, use the handle of the main window
      IF hFocusWnd = NULL THEN hFocusWnd = hWndMain
      ' // Give the WebBrowser control the opportunity to handle keystrokes
      IF AfxCAxHostForwardMessage(GetFocus, @uMsg) = FALSE THEN
         ' // Process Windows messages
         IF IsDialogMessageW(hFocusWnd, @uMsg) = 0 THEN
            TranslateMessage(@uMsg)
            DispatchMessageW(@uMsg)
          END IF
      END IF
   WEND
   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   SELECT CASE uMsg

      CASE WM_SYSCOMMAND
        ' Capture this message and send a WM_CLOSE message
        IF (wParam AND &HFFF0) = SC_CLOSE THEN
           SendMessageW hWnd, WM_CLOSE, 0, 0
           EXIT FUNCTION
        END IF

      CASE WM_COMMAND
         ' // If ESC key pressed, close the application sending an WM_CLOSE message
         SELECT CASE GET_WM_COMMAND_ID(wParam, lParam)
            CASE IDCANCEL
               IF GET_WM_COMMAND_CMD(wParam, lParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
            CASE IDC_POPUP
               IF GET_WM_COMMAND_CMD(wParam, lParam) = BN_CLICKED THEN
                  PopupWindow(hwnd)
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_SIZE
         IF wParam <> SIZE_MINIMIZED THEN
            ' // Resize the buttons
            DIM pWindow AS CWindow PTR = AfxCWindowPtr(hwnd)
            pWindow->MoveWindow GetDlgItem(hwnd, IDC_POPUP), pWindow->ClientWidth - 140, pWindow->ClientHeight - 40, 75, 23, CTRUE
         END IF

      CASE WM_CLOSE
         ' // Don't exit; let DefWindowProcW perform the default action

    CASE WM_DESTROY
         ' // Quit the application
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

   ' // Default processing of Windows messages
   FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

' ========================================================================================
FUNCTION PopupWindow (BYVAL hParent AS HWND) AS CWindow PTR

   DIM pWindow AS CWindow PTR = NEW CWindow
   pWindow->Create(hParent, "Popup window", @PopupWndProc, 0, 0, 0, 0, _
        WS_POPUPWINDOW OR WS_CAPTION OR WS_CLIPSIBLINGS OR WS_CLIPCHILDREN OR WS_THICKFRAME, _
        WS_EX_CONTROLPARENT OR WS_EX_WINDOWEDGE)
   pWindow->Brush = GetStockObject(WHITE_BRUSH)
   pWindow->SetClientSize(700, 400)
   pWindow->Center(pWindow->hWindow, hParent)
   ' // Display the window
   ShowWindow(pWindow->hWindow, SW_NORMAL)
   UpdateWindow(pWindow->hWindow)
   FUNCTION = pWindow

END FUNCTION
' ========================================================================================

' ========================================================================================
' Popup window procedure
' ========================================================================================
FUNCTION PopupWndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   SELECT CASE uMsg

      CASE WM_CREATE
         ' // Get a pointer to the CWindow class from the CREATESTRUCT structure
         DIM pWindow AS CWindow PTR = AfxCWindowPtr(lParam)
         IF pWindow THEN
            IF pWindow->hWindow = NULL THEN pWindow->hWindow = hwnd
            ' // Add a WebBrowser control
            DIM pwb AS CWebCtx PTR = NEW CWebCtx(pWindow, IDC_WEBBROWSER, 0, 0, pWindow->ClientWidth, pWindow->ClientHeight)
            ' // Navigate to a URL
            pwb->Navigate("http://www.planetsquires.com/protect/forum/index.php")
            SetPropW(pWindow->hWindow, "CWEBCTXPTR", CAST(HANDLE, pwb))
            ' // Optional: Wait for page load with a timeout of 10 seconds
            DIM lReadyState AS READYSTATE = pwb->WaitForPageLoad(10)
            ' // Set the focus in the page (the page must be fully loaded)
            pwb->SetFocus
         END IF
         EXIT FUNCTION

      CASE WM_SYSCOMMAND
        ' Capture this message and send a WM_CLOSE message
        IF (wParam AND &HFFF0) = SC_CLOSE THEN
           SendMessageW hWnd, WM_CLOSE, 0, 0
           EXIT FUNCTION
        END IF

      CASE WM_SIZE
         IF wParam <> SIZE_MINIMIZED THEN
            ' // Retrieve a pointer to the CWindow class
            DIM pWindow AS CWindow PTR = AfxCWindowPtr(hwnd)
            ' // Move the position of the control
            IF pWindow THEN pWindow->MoveWindow GetDlgItem(hwnd, IDC_WEBBROWSER), 0, 0, pWindow->ClientWidth, pWindow->ClientHeight, CTRUE
         END IF

      CASE WM_COMMAND
         SELECT CASE GET_WM_COMMAND_ID(wParam, lParam)
            CASE IDCANCEL
               ' // If ESC key pressed, close the application by sending an WM_CLOSE message
               IF GET_WM_COMMAND_CMD(wParam, lParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_CLOSE
         ' // Don't exit; let DefWindowProcW perform the default action

    CASE WM_DESTROY
         ' // Delete the CWewbCtx class
         DIM pwb AS CWebCtx PTR = CAST(CWebCtx PTR, GetPropW(hwnd, "CWEBCTXPTR"))
         IF pwb THEN Delete pwb
         ' // Delete the popup CWindow class
         DIM pWindow AS CWindow PTR = AfxCWindowPtr(hwnd)
         IF pWindow THEN Delete pWindow
         EXIT FUNCTION

   END SELECT

   ' // Default processing of Windows messages
   FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================
« Last Edit: October 22, 2018, 12:00:08 PM by Josť Roca »
Logged

Pierre Bellisle

  • FireFly3 User
  • Junior Member
  • *
  • Posts: 83
Re: Problem: Modeless form and CWebCtx control
« Reply #2 on: October 22, 2018, 11:51:07 AM »

"My attempts have ended up with either a GPF or freezing of the application"

Hi Paul,
This suggestion might be of interest.
When debugging code, like many of us, I also sometime get freeze and gpf.
So I adapted my pre-compiler utility to take care of that.
If I want to compile and some stuff is still in memory
or if worst, my app gone wild cloning itself to the infinite
then hitting my IDE compile button will bring a terminate/close dialog.

See Jump - Terminate

Added: One of these days, I will add a button to bring back windows that are simply out off screens.

« Last Edit: October 22, 2018, 02:55:51 PM by Pierre Bellisle »
Logged

Paul Squires

  • Administrator
  • Master Member
  • *****
  • Posts: 8635
  • Windows 10
    • PlanetSquires Software
Re: Problem: Modeless form and CWebCtx control
« Reply #3 on: October 22, 2018, 03:22:40 PM »

This has been very hard. Is it an exam? :)

You get an A+, 100%, and a Gold Star!!!  :-)
Your example seems to work perfectly. I had also started with your modeless template and attempted to add to it with the web browser code but I could not get it to work (I originally tried to add a modeless web browser form directly within WinFBE for the help system I am adding but that failed miserably so I tried to recreate it with the modeless template etc).
When I get home tonight I will analyze your code more closely to see how it differs from my code and to learn why yours works and mine failed. I will then build it into WinFBE. Thanks for taking the time to create the example. :)
Logged
Paul Squires
PlanetSquires Software
FireFly Visual Designer, WinFBE Editor

Paul Squires

  • Administrator
  • Master Member
  • *****
  • Posts: 8635
  • Windows 10
    • PlanetSquires Software
Re: Problem: Modeless form and CWebCtx control
« Reply #4 on: October 22, 2018, 03:23:23 PM »

"My attempts have ended up with either a GPF or freezing of the application"

Hi Paul,
This suggestion might be of interest.
When debugging code, like many of us, I also sometime get freeze and gpf.
So I adapted my pre-compiler utility to take care of that.
If I want to compile and some stuff is still in memory
or if worst, my app gone wild cloning itself to the infinite
then hitting my IDE compile button will bring a terminate/close dialog.

See Jump - Terminate

Added: One of these days, I will add a button to bring back windows that are simply out off screens.


Thanks Pierre! Great looking utility and seems to be quite useful. :)
Logged
Paul Squires
PlanetSquires Software
FireFly Visual Designer, WinFBE Editor

Josť Roca

  • Moderator
  • Master Member
  • *****
  • Posts: 3109
    • Jos
Re: Problem: Modeless form and CWebCtx control
« Reply #5 on: October 23, 2018, 01:14:13 AM »

A further check can be added to only execute

IF AfxCAxHostForwardMessage(GetFocus, @uMsg) = FALSE THEN

if GetParent(AfxGetControlHandle(GetFocus(), IDC_WEBBROWSER)) has returned a handle.

However, use GetFocus with AfxCAxHostForwardMessage because the focus won't be in the dialog or the OLE container, but in the web page.
« Last Edit: October 23, 2018, 09:51:03 AM by Josť Roca »
Logged

Paul Squires

  • Administrator
  • Master Member
  • *****
  • Posts: 8635
  • Windows 10
    • PlanetSquires Software
Re: Problem: Modeless form and CWebCtx control
« Reply #6 on: October 23, 2018, 10:56:15 AM »

Lol, Josť you wrote this over on the OxygenBasic forum and I just had to laugh because it is so true! I remember back in those days the push to create OCX's and the new rush of drag and drop programmers. I was one back in those days (for Windows programming) and it wasn't until I started dabbling in C and PowerBasic that I really got invested in API programming.

Quote
"Many years ago, a C++ programmer ironically thanked Microsoft for the creation of Visual Basic because it gave C++ programmers the opportunity to make money writing OCX's for it."

Logged
Paul Squires
PlanetSquires Software
FireFly Visual Designer, WinFBE Editor

Paul Squires

  • Administrator
  • Master Member
  • *****
  • Posts: 8635
  • Windows 10
    • PlanetSquires Software
Re: Problem: Modeless form and CWebCtx control
« Reply #7 on: October 23, 2018, 04:04:58 PM »

I think the big problem with my code was that I was not saving the reference returned from the creation of the web browser control. When it went out of scope then it would get destroyed. Makes sense now that I look at it but at the time I couldn't see the forest for the trees.
Logged
Paul Squires
PlanetSquires Software
FireFly Visual Designer, WinFBE Editor

Josť Roca

  • Moderator
  • Master Member
  • *****
  • Posts: 3109
    • Jos
Re: Problem: Modeless form and CWebCtx control
« Reply #8 on: October 23, 2018, 04:27:39 PM »

With a modal dialog we can create the instance of the class without NEW because the CWebCtx class won't we destroyed until the dialog ends, but with a modeless dialog we have to use NEW and DELETE.