• Welcome to PlanetSquires Forums.
 

WinFBE using CWindow #3

Started by Paul Squires, June 01, 2016, 07:23:48 PM

Previous topic - Next topic

José Roca

> I don't think that you ported all of your control wrappers to FB, right? I used a couple of my FireFly Functions for things like the Treeview.

Since there are macros for most one-line messages in Windowsx.bi and commctrl.bi, I plan to write an include file, AfxCtl.inc, with wrappers for more useful functions, such the ones that I have written to add toolbar buttons and separators, and the ones for tooltip controls. I will check my wrappers for PowerBASIC and translate the ones that I find worthwile.


Paul Squires

Quote from: Jose Roca on June 02, 2016, 02:37:42 AM
Why using pTabPage1->SetFont("", 12, FW_BOLD) after DIM pTabPage2 AS CTabPage PTR = NEW CTabPage causes problems?

Why moving the window creation from frmOptionsEditor_Show to frmOptions.inc works?

Looks like a compiler bug to me.

That is very interesting. I wish I had an explanation as well. Could very well be some sort of compiler bug. Seems so strange through.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

It seems like the class is working correctly. I ran the source through FBDebugger and traced all the calls. The font is being assigned to the child controls. The code below shows that the font is actually assigned correctly to a child control. The problem is that the font is not being displayed. Weird.


Dim As HWnd hCtrl = _
   pWindow.AddControl("LABEL", pWindow.hWindow, IDC_FRMOPTIONSEDITOR_LBLTABSIZE, "Tab Size:", 38, 273, 86, 17, _
        WS_CHILD Or WS_VISIBLE Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN Or SS_LEFT Or SS_NOTIFY, _
        WS_EX_LEFT Or WS_EX_LTRREADING)

Dim As HFONT hFont = AfxGetWindowFont(hCtrl)
Dim As LOGFONT lf
GetObject(hFont, Len(lf), @lf)

Print pWindow.Font, hFont
Print lf.lfFaceName

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

The two codes that have this problem, your editor and my tab control demo, have one thing in common:  both create child windows without a message pump to be hidden or displayed at convenience.

Paul Squires

This font issue is driving me crazy!   :)

Please try the attached code. Something must get screwed up with the class pointer between the time the controls are created to the time that the child form is moved into place and shown.

The two areas to look at are:
frmOptions.inc :: frmOptions_OnNotify
frmOptionsEditor.inc :: frmOptionsEditor_Show

The debug printout to the console screen shows a different font handle existing for the main child window from one call to the next.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#20
Hi Paul,

You MUST NOT create the instance of CWindow in frmOptionsEditor_Show, unless you use NEW because when the function ends pWindow goes out of scope and the class is destroyed and the font deleted.

I posted code creating the new CWindow class before calling frmOptionsEditor_Show and passing a pointer to the function.

Paul Squires

{face palm} Of course! Oh my, I hadn't thought about the scope issue and the class being destroyed. That certainly makes sense! I will revisit my code again today.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

Hi Jose,

I am going to use the following syntax exclusively from now on because it gives the most versatility.

Main Form:
   Dim pWindow As CWindow Ptr = New CWindow("WinFBE")

or simply
   Dim pWindow As CWindow Ptr = New CWindow

And then use pointer syntax. To create the controls:

   pWindow->AddControl("LABEL", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_LBLTABSIZE, "Tab Size:", 38, 273, 86, 17, _
        WS_CHILD Or WS_VISIBLE Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN Or SS_LEFT Or SS_NOTIFY, _
        WS_EX_LEFT Or WS_EX_LTRREADING)
   pWindow->AddControl("TEXTBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_TXTTABSIZE, "", 2, 270, 30, 20, _
        WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or ES_LEFT Or ES_AUTOHSCROLL Or ES_NUMBER, _
        WS_EX_CLIENTEDGE Or WS_EX_LEFT Or WS_EX_LTRREADING Or WS_EX_RIGHTSCROLLBAR)


I am now going to test for the best place to do the DELETE in order to clean up the allocated memory. Most likely in the WM_DESTROY or WM_NCDESTROY should do it. WM_DESTROY seems to work well.



' ========================================================================================
' Process WM_DESTROY message for window/dialog: frmOptionsEditor
' ========================================================================================
Function frmOptionsEditor_OnDestroy(HWnd As HWnd) As LRESULT
   ' Get the pointer to the manually allocated memory and
   ' then free it with DELETE.
   Dim pWindow As CWindow Ptr = AfxCWindowPtr(HWnd)
   
   Delete pWindow

   Function = 0
End Function


' ========================================================================================
' frmOptionsEditor Window procedure
' ========================================================================================
Function frmOptionsEditor_WndProc( ByVal HWnd   As HWnd, _
                                   ByVal uMsg   As UINT, _
                                   ByVal wParam As WPARAM, _
                                   ByVal lParam As LPARAM _
                                   ) As LRESULT

   Select Case uMsg
      HANDLE_MSG (HWnd, WM_DESTROY, frmOptionsEditor_OnDestroy)
   End Select

   ' for messages that we don't deal with
   Function = DefWindowProc(HWnd, uMsg, wParam, lParam)

End Function


After implementing these changes, everything in the project is now working perfectly. All fonts, etc are displaying correctly.


Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

With the latest version of CWindow , you can save some typing if you want using


   pWindow->AddControl("LABEL",  , IDC_FRMOPTIONSEDITOR_LBLTABSIZE, "Tab Size:", 38, 273, 86, 17, _
        WS_CHILD Or WS_VISIBLE Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN Or SS_LEFT Or SS_NOTIFY, _
        WS_EX_LEFT Or WS_EX_LTRREADING)


instead of


   pWindow->AddControl("LABEL", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_LBLTABSIZE, "Tab Size:", 38, 273, 86, 17, _
        WS_CHILD Or WS_VISIBLE Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN Or SS_LEFT Or SS_NOTIFY, _
        WS_EX_LEFT Or WS_EX_LTRREADING)


If you don't specify the parent, the AddControl method will use the handle of the main window.

José Roca

If you're goig to use the Scintilla editor, that does not support UTF-16, but UTF-8, you can get WYSIWYG enabling UTF-8 and also letting the user to choose the charset.

However, as Windows controls don't understand UTF-8, applications that use it must convert the UTF-8 string to UTF-16 before sending it to the control.

This can be achieved using my overloaded AfxUcode function (in AfxWin.inc), that supports passing a UTF-8 encoded string and returns a BSTR, e.g.


' Usage example (Russian UTF8 string to BSTR)
DIM bs AS BSTR
bs = AfxUcode("Дми́трий Дми́триевич", CP_UTF8)
MessageBoxW 0, bs, "", MB_OK
IF bs THEN SysFreeString(bs)


or using a WSTRING passed by reference:


DIM wszText AS WSTRING * 260
AfxUcode("Дми́трий Дми́триевич", wszText, SIZEOF(wszText), CP_UTF8)
MessageBoxW 0, wszText, "", MB_OK
DIM s AS STRING
s = AfxAcode(wszText, CP_UTF8)
MessageBoxW 0, s, "", MB_OK



José Roca

AfxUcode/AfxAcode also allow to pass a UTF-16 string:


DIM bs AS BSTR
bs = AfxUcode(CHR(209, 229, 236, 229, 237), 1251)
MessageBoxW 0, bs, "", MB_OK


I have used CHR because Scintilla doesn't support UTF-16, but it can be a variable with text read from disk.

José Roca

The FreeBASIC functions WSTR and STR can't be used for this purpose because don't allow to pass a code page. In PowerBASIC, I convinced Bob to add an optional code page to UCODE/ACODE.

José Roca

I have written interface declarations for scrrun, the Microsoft Runtime Library, that includes the Dictionary object.

Currently, it can be used this way:


#include once "windows.bi"
#INCLUDE ONCE "Afx/AfxCOM.inc"
#INCLUDE ONCE "Afx/AfxVariants.inc"
#INCLUDE ONCE "Afx/AfxScrRun.bi"

CoInitialize NULL

' // Create an instance of the Dictionary object
DIM pDic AS Afx_IDictionary PTR
pDic = AfxNewCom("Scripting.Dictionary")
IF pDic THEN END

DIM vKey AS VARIANT = AfxVarFromStr("a")
DIM vItem AS VARIANT = AfxVarFromStr("Athens")
pDic->Add(@vKey, @vItem)

VariantClear(@vItem)
pDic->get_Item(@vKey, @vItem)
print *CAST(WSTRING PTR, vItem.bstrVal)

VariantClear(@vKey)
VariantClear(@vItem)
IF pDic THEN pDic->Release

print "press esc"
sleep

CoUninitialize


But I have yet to write wrappers for variants and many other things. Not an easy task without native support for BSTRs and VARIANTs, and much less since they have broken the definition of BSTR.


José Roca

#28
Which name do you prefer: AfxNewCom, AfxNewObject, AfxCreateObject, other...

This overloaded function allows to create objects in all the ways possible: using progIDs, CLIDs... registered or unregistered... licensed or not...

Must decide the name before doing more work.

Paul Squires

I would say AfxNewCom because anything with "Object" in it may be confusing to FB'ers who may automatically associate it with the object (OOP) version of the TYPE structure. Not sure, but that would be my first reaction.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer