CWindow Release Candidate 24
I have removed many of the COM related stuff: CBSTR, CVARIANT, CSafeArray, CDispInvoke, CDicObj and the ADO classes.
I have added CWstrArray, that although internally uses a safe array of BSTRs, all the string parameters and return values are CWSTRs.
31.10.2016 : Updated with the latest version of CWSTR.inc
I have also modified the TypeLib Browser to use CWSTR instead of CBSTR.
The adaptation of the Open and Save file dialog has been a little tricky. Only a C programmer can think of using embedded nulls as separators in a null terminated string... Crazy people! I could have used the COM API, but as Marc, the only user of this tool, is still working with XP...
Google Map example
' ########################################################################################
' Microsoft Windows
' Contents: WebBrowser - Google map
' 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/CWebBrowser/CWebBrowser.inc"
USING Afx
CONST IDC_WEBBROWSER = 1001
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
' ========================================================================================
' Build the script
' ========================================================================================
FUNCTION BuildScript () AS STRING
DIM s AS STRING
s = "<!DOCTYPE html>"
s += "<html>"
s += " <head>"
s += " <meta http-equiv='X-UA-Compatible' content='IE=edge'>"
s += " <style>"
s += " html, body, #map-canvas"
s += " {"
s += " height: 100%;"
s += " margin: 0px;"
s += " padding: 0px"
s += " }"
s += " </style>"
s += " <script src='https://maps.googleapis.com/maps/api/js?v=3'></script>"
s += " <script>"
s += " var globalLatLng = '';"
s += " function initialize()"
s += " {"
s += " var mapOptions ="
s += " {"
s += " zoom: 8,"
s += " center: new google.maps.LatLng(51.5, -0.2),"
s += " mapTypeId: google.maps.MapTypeId.ROADMAP"
s += " };"
s += " var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);"
s += " }"
s += " google.maps.event.addDomListener(window, 'load', initialize);"
s += " </script>"
s += " </head>"
s += " <body>"
s += " <div id='map-canvas'></div>"
s += " </body>"
s += "</html>"
FUNCTION = s
END FUNCTION
' ========================================================================================
' ========================================================================================
' 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, "WebBrowser - Google map", @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 WebBrowser control
DIM pwb AS CWebBrowser = CWebBrowser(@pWindow, IDC_WEBBROWSER, 0, 0, pWindow.ClientWidth, pWindow.ClientHeight)
' // Set the IDocHostUIHandler interface
pwb.SetUIHandler
' // Build the script
DIM s AS STRING = BuildScript
' // Save the script as a temporary file
DIM wszPath AS WSTRING * MAX_PATH = AfxSaveTempFile(s, "html")
' // Navigate to the path
pwb.Navigate(wszPath)
' // Processes pending Windows messages to allow the page to load
AfxPumpMessages
' // Kill the temporary file
KILL wszPath
' // Displays the window and dispatches the Windows messages
FUNCTION = pWindow.DoEvents(nCmdShow)
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
' // 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_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
' ========================================================================================
CWSTR.INC update
I have optimized some of the constructors to not preallocate memory if unneeded and added overloads for LEFT, RIGHT, VAL and the & operator. Now they can be used without having to double deference the string, although doing it is still, and will ever be, the fastest way. Using the operator + with CWSTR is also faster than using &.
I also have added the function pthis that returns the address of the CWSTR, since @ and VARPTR are used by the class to return the address of the underlying string buffer. You only will need this function if you want to declare a parameter as BYVAL CWSTR PTR instead of BYREF CWSTR.
Modified AfxUcode to work with CWSTR, The previous version used a BSTR.
' ========================================================================================
' Translates ansi bytes to unicode bytes.
' Parameters:
' - ansiStr = An ansi or UTF8 string.
' - nCodePage = The code page used in the conversion, e.g. 1251 for Russian.
' If you specify CP_UTF8, the returned string will be UTF8 encoded.
' If you don't pass an unicode page, the function will use CP_ACP (0), which is the
' system default Windows ANSI code page.
' Return value:
' The converted string as a CWSTR.
' ========================================================================================
PRIVATE FUNCTION AfxUcode (BYREF ansiStr AS CONST STRING, BYVAL nCodePage AS LONG = 0) AS CWSTR
IF nCodePage = CP_UTF8 THEN
DIM dwLen AS DWORD = MultiByteToWideChar(CP_UTF8, 0, STRPTR(ansiStr), LEN(ansiStr), NULL, 0)
IF dwLen THEN
DIM cws AS CWSTR = SPACE(dwLen)
dwLen = MultiByteToWideChar(CP_UTF8, 0, STRPTR(ansiStr), LEN(ansiStr), @cws, dwLen * 2)
IF dwLen THEN RETURN cws
END IF
ELSE
DIM cws AS CWSTR = SPACE(LEN(ansiStr))
DIM dwLen AS DWORD = MultiByteToWideChar(nCodePage, MB_PRECOMPOSED, STRPTR(ansiStr), LEN(ansiStr), @cws, LEN(ansiStr) * 2)
IF dwLen THEN RETURN cws
END IF
END FUNCTION
' ========================================================================================
CWSTR.INC update
Changed the constructor with the CodePage parameter to accept the Capacity parameter instead. This way, we can pre-allocate the capacity when declaring the variable, e.g. DIM cws AS CWSTR = 260 * 2.
Added a boolean fAttach parameter to the constructor that accepts a WSTRING pointer to allow faster concatenations using the & operators.
Modified the & operators for faster concatenations.
CWSTR.INC update
Some additional changes and optimizations. Thanks to Marc Pons for testing the class and for his suggestions.