CWindow RC 23

Started by José Roca, October 03, 2016, 03:04:12 PM

Previous topic - Next topic

José Roca

CWindow Release Candidate 23

I have finished the CWebBrowser class.

Besides allowing to call all the relevant methods of the IWebBrowser2 interface, you can sink to the wanted events in a similar way as with VB6.

Events of the IDochHostUIHandler2 inteface are also supported for easy customization.

Events from the loaded page are supported in a generic way, i.e. there is not a callback for every possible event (there are too many) but just a function in which you can decide what to do according to the passe identifier of the event.

The most common need is to detect if a certain element in the web page, e.g. a button, has been clicked. You can do it by subscribing to the web page events


pwb.SetEventProc("HtmlDocumentEvents", @WebBrowser_HtmlDocumentEventsProc)


and then processing the event


PRIVATE FUNCTION WebBrowser_HtmlDocumentEventsProc (BYVAL hwndContainer AS HWND, BYVAL dispid AS LONG, BYVAL pEvtObj AS IHTMLEventObj PTR) AS BOOLEAN

   SELECT CASE dispid

      CASE DISPID_HTMLELEMENTEVENTS2_ONCLICK   ' // click event
         ' // Get a reference to the element that has fired the event
         DIM pElement AS IHTMLElement PTR
         IF pEvtObj THEN pEvtObj->lpvtbl->get_srcElement(pEvtObj, @pElement)
         IF pElement = NULL THEN EXIT FUNCTION
         DIM cbsHtml AS CBSTR   ' // Outer html
         pElement->lpvtbl->get_outerHtml(pElement, @cbsHtml)
'         DIM cbsId AS CBSTR   ' // identifier
'         pElement->lpvtbl->get_id(pElement, @cbsID)
         pElement->lpvtbl->Release(pElement)
         AfxMsg cbsHtml
         RETURN TRUE

   END SELECT

   RETURN FALSE

END FUNCTION


Full example


' ########################################################################################
' Microsoft Windows
' Contents: WebBrowser customization test
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2016 Jose 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/AfxCtl.inc"
#INCLUDE ONCE "Afx/CWebBrowser/CWebBrowser.inc"
USING Afx

CONST IDC_WEBBROWSER = 1001
CONST IDC_SATUSBAR = 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)

DECLARE FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

' // Forward declarations
DECLARE SUB WebBrowser_StatusTextChangeProc (BYVAL hwndContainer AS HWND, BYVAL pwszText AS WSTRING PTR)
DECLARE SUB WebBrowser_DocumentCompleteProc (BYVAL hwndContainer AS HWND, BYVAL pdisp AS IDispatch PTR, BYVAL vUrl AS VARIANT PTR)
DECLARE SUB WebBrowser_BeforeNavigate2Proc (BYVAL hwndContainer AS HWND, BYVAL pdisp AS IDispatch PTR, _
    BYVAL vUrl AS VARIANT PTR, BYVAL Flags AS VARIANT PTR, BYVAL TargetFrameName AS VARIANT PTR, _
    BYVAL PostData AS VARIANT PTR, BYVAL Headers AS VARIANT PTR, BYVAL pbCancel AS VARIANT_BOOL PTR)
DECLARE FUNCTION WebBrowser_HtmlDocumentEventsProc (BYVAL hwndContainer AS HWND, BYVAL dispId AS LONG, BYVAL pEvtObj AS IHTMLEventObj PTR) AS BOOLEAN
DECLARE FUNCTION DocHostUI_ShowContextMenuProc (BYVAL hwndContainer AS HWND, BYVAL dwID AS DWORD, BYVAL ppt AS POINT PTR, BYVAL pcmdtReserved AS IUnknown PTR, BYVAL pdispReserved AS IDispatch PTR) AS HRESULT
DECLARE FUNCTION DocHostUI_GetHostInfo (BYVAL hwndContainer AS HWND, BYVAL pInfo AS DOCHOSTUIINFO PTR) AS HRESULT
DECLARE FUNCTION DocHostUI_TranslateAccelerator (BYVAL hwndContainer AS HWND, BYVAL lpMsg AS LPMSG, BYVAL pguidCmdGroup AS const GUID PTR, BYVAL nCmdID AS DWORD) AS HRESULT

' ========================================================================================
' 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
   ' // The recommended way is to use a manifest file
   AfxSetProcessDPIAware

   ' // Creates the main window
   DIM pWindow AS CWindow
   ' -or- DIM pWindow AS CWindow = "MyClassName" (use the name that you wish)
   DIM hwndMain AS HWND = pWindow.Create(NULL, "Embedded WebBrowser control with events and customization", @WndProc)
   ' // Sizes it by setting the wanted width and height of its client area
   pWindow.SetClientSize(750, 450)
   ' // Centers the window
   pWindow.Center

   ' // Add a status bar
   DIM hStatusbar AS HWND = pWindow.AddControl("Statusbar", , IDC_SATUSBAR)

   ' // Add a WebBrowser control
   DIM pwb AS CWebBrowser = CWebBrowser(@pWindow, IDC_WEBBROWSER, 0, 0, pWindow.ClientWidth, pWindow.ClientHeight)
   ' // Connect events
   pwb.Advise
   ' // Set event callback procedures
   pwb.SetEventProc("StatusTextChange", @WebBrowser_StatusTextChangeProc)
   pwb.SetEventProc("DocumentComplete", @WebBrowser_DocumentCompleteProc)
   pwb.SetEventProc("BeforeNavigate2", @WebBrowser_BeforeNavigate2Proc)
   pwb.SetEventProc("HtmlDocumentEvents", @WebBrowser_HtmlDocumentEventsProc)
   ' // Set the IDocHostUIHandler interface
   pwb.SetUIHandler
   ' // Set event callback procedures
   pwb.SetUIEventProc("ShowContextMenu", @DocHostUI_ShowContextMenuProc)
   pwb.SetUIEventProc("GetHostInfo", @DocHostUI_GetHostInfo)
   pwb.SetUIEventProc("TranslateAccelerator", @DocHostUI_TranslateAccelerator)
   ' // Navigate to a URL
   pwb.Navigate("http://com.it-berater.org/")
'   pwb.Navigate("http://www.jose.it-berater.org/smfforum/index.php")

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

   ' // Dispatch Windows messages
   DIM uMsg AS MSG
   WHILE (GetMessageW(@uMsg, NULL, 0, 0) <> FALSE)
      IF AfxForwardMessage(GetFocus, @uMsg) = FALSE THEN
         IF IsDialogMessageW(hWndMain, @uMsg) = 0 THEN
            TranslateMessage(@uMsg)
            DispatchMessageW(@uMsg)
         END IF
      END IF
   WEND
   FUNCTION = uMsg.wParam

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

' ========================================================================================
' Main 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_COMMAND
         SELECT CASE LOWORD(wParam)
            CASE IDCANCEL
               ' // If ESC key pressed, close the application by sending an WM_CLOSE message
               IF HIWORD(wParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_SIZE
         ' // Optional resizing code
         IF wParam <> SIZE_MINIMIZED THEN
            ' // Resize the status bar
            DIM hStatusBar AS HWND = GetDlgItem(hwnd, IDC_SATUSBAR)
            SendMessage hStatusBar, uMsg, wParam, lParam
            ' // Calculate the size of the status bar
            DIM StatusBarHeight AS DWORD, rc AS RECT
            GetWindowRect hStatusBar, @rc
            StatusBarHeight = rc.Bottom - rc.Top
            ' // 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 - StatusBarHeight / pWindow->ryRatio, CTRUE
         END IF

    CASE WM_DESTROY
         ' // Ends the application by sending a WM_QUIT message
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

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

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

' ========================================================================================
' Process the WebBrowser StatusTextChange event.
' ========================================================================================
SUB WebBrowser_StatusTextChangeProc (BYVAL hwndContainer AS HWND, BYVAL pwszText AS WSTRING PTR)
   IF pwszText THEN StatusBar_SetText(GetDlgItem(GetParent(hwndContainer), IDC_SATUSBAR), 0, pwszText)
END SUB
' ========================================================================================

' ========================================================================================
' Process the WebBrowser DocumentComplete event.
' ========================================================================================
SUB WebBrowser_DocumentCompleteProc (BYVAL hwndContainer AS HWND, BYVAL pdisp AS IDispatch PTR, BYVAL vUrl AS VARIANT PTR)
   ' // The vUrl parameter is a VT_BYREF OR VT_BSTR variant
   ' // It can be a VT_BSTR variant or a VT_ARRAY OR VT_UI1 with a pidl
   DIM varUrl AS VARIANT
   VariantCopyInd(@varUrl, vUrl)
   StatusBar_SetText(GetDlgItem(GetParent(hwndContainer), IDC_SATUSBAR), 0, "Document complete: " & AfxVarToStr(@varUrl))
   VariantClear(@varUrl)
END SUB
' ========================================================================================

' ========================================================================================
' Process the IDocHostUIHandler ShowContextMenu event.
' ========================================================================================
FUNCTION DocHostUI_ShowContextMenuProc (BYVAL hwndContainer AS HWND, BYVAL dwID AS DWORD, BYVAL ppt AS POINT PTR, BYVAL pcmdtReserved AS IUnknown PTR, BYVAL pdispReserved AS IDispatch PTR) AS HRESULT
   ' // This event notifies that the user has clicked the right mouse button to show the
   ' // context menu. We can anulate it returning %S_OK and show our context menu.
   ' // Do not allow to show the context menu
'   AfxMsg "Sorry! Context menu disabled"
'   RETURN S_OK
   ' // Host did not display its UI. MSHTML will display its UI.
   RETURN S_FALSE
END FUNCTION
' ========================================================================================

' ========================================================================================
' Process the IDocHostUIHandler GetHostInfo event.
' ========================================================================================
PRIVATE FUNCTION DocHostUI_GetHostInfo (BYVAL hwndContainer AS HWND, BYVAL pInfo AS DOCHOSTUIINFO PTR) AS HRESULT
   IF pInfo THEN
      pInfo->cbSize = SIZEOF(DOCHOSTUIINFO)
      pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER OR DOCHOSTUIFLAG_THEME OR DOCHOSTUIFLAG_DPI_AWARE
      pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT
      pInfo->pchHostCss = NULL
      pInfo->pchHostNS = NULL
   END IF
   RETURN S_OK
END FUNCTION
' ========================================================================================

' ========================================================================================
' Process the IDocHostUIHandler TranslateAccelerator event.
' ========================================================================================
PRIVATE FUNCTION DocHostUI_TranslateAccelerator (BYVAL hwndContainer AS HWND, BYVAL lpMsg AS LPMSG, BYVAL pguidCmdGroup AS const GUID PTR, BYVAL nCmdID AS DWORD) AS HRESULT
   ' // When you use accelerator keys such as TAB, you may need to override the
   ' // default host behavior. The example shows how to do this.
    IF lpMsg->message = WM_KEYDOWN AND lpMsg->wParam = VK_TAB THEN
       RETURN S_FALSE   ' S_OK to disable tab navigation
    END IF
   ' // Return S_FALSE if you don't process the message
   RETURN S_FALSE
END FUNCTION
' ========================================================================================

' ========================================================================================
' Fires before navigation occurs in the given object (on either a window or frameset element).
' ========================================================================================
SUB WebBrowser_BeforeNavigate2Proc (BYVAL hwndContainer AS HWND, BYVAL pdisp AS IDispatch PTR, _
    BYVAL vUrl AS VARIANT PTR, BYVAL Flags AS VARIANT PTR, BYVAL TargetFrameName AS VARIANT PTR, _
    BYVAL PostData AS VARIANT PTR, BYVAL Headers AS VARIANT PTR, BYVAL pbCancel AS VARIANT_BOOL PTR)

'   ' // Sample code to redirect navigation to another url
'   IF AfxVarToStr(vUrl) = "http://com.it-berater.org/" THEN
'      ' // Get a reference to the Afx_IWebBrowser2 interface
'      DIM pwb AS Afx_IWebBrowser2 PTR = cast(Afx_IWebBrowser2 PTR, cast(ULONG_PTR, pdisp))
'      IF pwb THEN
'         ' // Stop loading the page
'         pwb->Stop
'         ' // Cancel the navigation operation
'         *pbCancel = VARIANT_TRUE
'         ' // Navigate to another new url
'         DIM cvNewUrl AS CVARIANT = "http://www.planetsquires.com/protect/forum/index.php"
'         pwb->Navigate2(@cvNewUrl)
'      END IF
'   END IF

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

' ========================================================================================
' For cancelable document events return TRUE to indicate that Internet Explorer should
' perform its own event processing or FALSE to cancel the event.
' ========================================================================================
PRIVATE FUNCTION WebBrowser_HtmlDocumentEventsProc (BYVAL hwndContainer AS HWND, BYVAL dispid AS LONG, BYVAL pEvtObj AS IHTMLEventObj PTR) AS BOOLEAN

   SELECT CASE dispid

      CASE DISPID_HTMLELEMENTEVENTS2_ONCLICK   ' // click event
         ' // Get a reference to the element that has fired the event
         DIM pElement AS IHTMLElement PTR
         IF pEvtObj THEN pEvtObj->lpvtbl->get_srcElement(pEvtObj, @pElement)
         IF pElement = NULL THEN EXIT FUNCTION
         DIM cbsHtml AS CBSTR   ' // Outer html
         pElement->lpvtbl->get_outerHtml(pElement, @cbsHtml)
'         DIM cbsId AS CBSTR   ' // identifier
'         pElement->lpvtbl->get_id(pElement, @cbsID)
         pElement->lpvtbl->Release(pElement)
         AfxMsg cbsHtml
         RETURN TRUE

   END SELECT

   RETURN FALSE

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


I have reuploaded the headers incorporating the changes posted in reply #12.

José Roca

Because of the lack of response, I think that I'm going to stop posting, unless I find bugs that require an update.

I would like to know if it is because...

1) There is not much interest in Free Basic among the members of this forum.

2) There is not interest in this framework.

3) Other reasons.

Richard Kelly

I'm at the beginning of my transition to FB and I follow your posts with much interest. It is your work that convinced me I could make a go of FB. I have a large toolbox of stuff (classes like PDF creation, SMTP, tcp/ip, SQLite client/server, etc) to port, cCalendar being the first before I begin the rewrite of my applications. I'm counting on Paul to integrate cWindows as completely as possible to provide the foundation for first rate Windows apps. I'm not into all the technical details as you are - my area is the end game and developing software that uniquely solutions commercial lines of business. For that, I need you and Paul and appreciate all that the both of you do.

José Roca

So, if I haven't misunderstood you, you're waiting for a visual designer.

Marc Pons

Jose

As always you are doing a very valuable job.

Be sure , I'm very interrested on FreeBasic , on your Framework and globally on your posts.

I'm still "absorbing" the big amount of code you are producing.

What I'm less interrested is  in the CWebBrowser  : for me it is more a way ( a sample )on how to use the COM.

As you know,i'm more interrested on the generic tools to facilitate the use of COM under Freebasic.

I'm currently converting to freebasic an application i've previously done with powerbasic interfacing pfdcreator to convert to pfd many types of documents ( because pdfcreator changed completly their COM interfaces), i will use lot of your solutions.

The generation code of your typelib browser will play a big role.
Still do not understand how to use your Colecon class on  IUNKNOWN interface  and how to fire IUNKNOWN event interface...


If you think your Freebasic contribution not enougth followed here, why not extend it on  posting on the official Freebasic Forum , and / or in this one  https://www.freebasic-portal.de/ german but no problem to put english info.

James Fuller

Jose,
  I understand your reluctance to continue posting, but the sheer volume of your contributions, takes a while to absorb. Please continue your FreeBasic research and post your findings here.
I believe a majority of advanced Fb coders are Linux centric. Novice Fb Windows coders may very well just be overwhelmed with the material you have posted here.
Much of your code is not very BASIC in appearance. I know you are not a big MACRO fan but maybe that is a direction that would interest more people.
  Thank you for your dedication.

James



Klaas Holland

Jose,

Thank you for your contribution to the FreeBasic world.
Your knowledge of programming is far beyond mine.

I converted almost all of my FF-PB programs into FF-FreeBasic thanks to the help of Paul.
However these programs are not High DPI Aware.

It would be great if Paul implements all of your work in FireFly, so we will be able to use it in FireFly.

This could be the way to persuade the PB-people to switch to FreeBasic.

Klaas


Richard Kelly

Quote from: Jose Roca on October 04, 2016, 02:21:20 AM
So, if I haven't misunderstood you, you're waiting for a visual designer.

Yes - that is the logical endgame for your work.

José Roca

#8
Quote
Still do not understand how to use your Colecon class on  IUNKNOWN interface  and how to fire IUNKNOWN event interface...

And I still don't understand what you mean. I never have seen a visual OCX which inherits directly from IUnknown instead of IDispatch. Can you give me an example?

The OLE Container is a class to host visual ActiveX controls. Non visual ActiveX don't need an OLE Container.

Quote
What I'm less interrested is  in the CWebBrowser  : for me it is more a way ( a sample )on how to use the COM.

Probably you don't realize all that can be done with it.

José Roca

Quote from: Richard Kelly on October 04, 2016, 09:11:05 AM
Quote from: Jose Roca on October 04, 2016, 02:21:20 AM
So, if I haven't misunderstood you, you're waiting for a visual designer.

Yes - that is the logical endgame for your work.

If a visual designer is a prerequisite to use the framework then we are screwed because we don't know if this will ever happen or when.

Any project without participants dies because of lack of motivation.

Jean-pierre Leroy

Jose,

You have done a huge work with your framework; almost everything is avaible including ODBC (which is nice to replace SQLtools usually used with PB).

I read each of your posts with great attention.

Currently I'm still using FireFly+PowerBASIC+SQLitening+SQLTools+VPE (Virtual Print Engine) to create 32 bits only, ansi only, client/serveur windows software (business applications).

It will be easier (at least for me) to switch to FreeBasic when a visual designer coupled with your framework will be available.

Richard Kelly

#11
Quote from: Jose Roca on October 04, 2016, 02:03:37 PM
Quote from: Richard Kelly on October 04, 2016, 09:11:05 AM
Quote from: Jose Roca on October 04, 2016, 02:21:20 AM
So, if I haven't misunderstood you, you're waiting for a visual designer.

Yes - that is the logical endgame for your work.

If a visual designer is a prerequisite to use the framework then we are screwed because we don't know if this will ever happen or when.

Any project without participants dies because of lack of motivation.

There is much in the framework I will use as part of the classes I have yet to port over. cWindows is the key integration into a visual designer and I hope to see something this year.

I do understand participation. You are the only one who posted on my cCalendar effort over much of the past months and I spent roughly 50 hours on it. Perhaps this forum is in decline.

José Roca

#12
Modified the following wrapper functions in which the parameter was being wrongly cast to the address of the passed pointer (I still make this error sometimes because I have used @ with pointers so many times with PowerBASIC).

ComboBoxEx_InsertItem
Syslink_GetItem
SysLink_HitTest
SysLink_SetItem
TreeView_GetItemEx

I have reuploaded the headers incorporating these changes.

Petrus Vorster

I read each and every post you make, although I don't understand half of it.
Many of us are dependent on a visual designer and we truly hope that it would happen because this massive amount of stuff you develop combined with a visual designer from Paul will enable the rest of us to excel like never before.

I mean, you made Powerbasic Rock. You and Paul made it accessible to me and now I hope that you two will combine once again with all your lovely inspiring computer voodoo you do so a dummy like me can do cool stuff too.

We are here, every day. Please don't stop with your magic.
I just don't post anything because I cant contribute any value to your work!!!

All of us appreciate the stuff you do. Without it most will be lost!! thanks a million.
-Regards
Peter

José Roca

Thanks to all for answering my questions.

As I'm not willing to officially release something that has not been thoroughly tested, I'm going to prepare a stripped version with all the COM stufff removed. I will keep CWindow, the wrappers for the Windows API and controls, the string functions, the GDI+ helpers (not the classes) and the CWSTR data type. Maybe something more that I'm forgetting. Everything else will be removed. That is, I'm only going to keep what Paul will need to finish his editor.