Hi Jose,
I am taking my first shot at adding the "Environment Options" dialog. I think I am having trouble with the child forms and the controls not having the font set. When I run the program, the controls show with the default system font. Any idea why?
I will check, step by step.
In the first place, I have needed to add a couple of CASTs.
Also, the program remained in memory, so I have added PostQuitMessage.
' ========================================================================================
' Process WM_DESTROY message for window/dialog: frmOptions
' ========================================================================================
Function frmOptions_OnDestroy(HWnd As HWnd) As LRESULT
PostQuitMessage(0)
Function = 0
End Function
Oh, yes, I forgot that PostQuitMessage in order to get out of the message loop for the modal window. I have now added it. I will have a lot of time tomorrow to work on these forms so hopefully after tomorrow much of the environment options will be workable.
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.
...I fixed those missing CAST's and missing Function values.
Don't know yet what its happening. If I made the options dialog a popup window, add a message pump and process the messages, and disable the parent, the controls are created as it should.
Yes, the main FRMOPTIONS window is setting the fonts okay as well. It only happens when I am using the embedded child forms FRMOPTIONSEDITOR, FRMOPTIONSCOLORs, FRMOPTIONSCOMPILER. Must have something to do with the message pump. I will test tomorrow as well.
Hi Jose,
Maybe you can add a property to the CWindow class to be able to retrieve the default font face name (m_wszDefaultFontName)? Some of my controls need to be set at different sizes. I am using the class's CreateFont method but I must pass the name of the font. Depending on the version of operating system, I would want to use a different default font name. You already do this for the class when the main window is created so rather than me having to do a AfxWindowsVersion and store the font name, it would be more convenient to get it via the CWindow class.
...or...
Modify the CreateFont method so that if I pass a null string for the font name to the CreateFont method it will use the default font?
Dim As HFONT hFont = pWindow.CreateFont("", 14, FW_BOLD)
What do you think?
Hi Jose, I updated the first post to include a new attachment with all of the changes mentioned in this thread so far. It also has code for handling different color for the "Category Label". Basically a foreground blue color on a standard button face color background.
The most strange is that you're doing more or less what I do with the tab pages of a tab control, and they work fine. Also if I pass the font handle of the main window to the options form and set this font, the font that changes is the one of the main form, that becomes smaller!
> What do you think?
I will do.
I don't understand what is happening with the fonts. How can it be that trying to change the font of the frmOptionsEditor what changes is the font of frmOptions?
I have added the DefaultName property and also changed SetFont and CreateFont to allow to pass an empty string for the font name.
Don't know if there is a bug in the compiler or what, but if I change in frmOptions.inc
' Create the main window and child controls
' frmOptionsEditor_Show( pWindow.hWindow )
Dim pWinOpEd As CWindow
HWND_FRMOPTIONSEDITOR = pWinOpEd.Create( pWindow.hWindow, "", @frmOptionsEditor_WndProc, 0, 0, 354, 319, _
WS_CHILD Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN, _
WS_EX_CONTROLPARENT Or WS_EX_LEFT Or WS_EX_LTRREADING Or WS_EX_RIGHTSCROLLBAR)
pWinOpEd.SetClientSize(354, 319)
frmOptionsEditor_Show(@pWinOpEd)
and in frmOptionsEditor_Show
' ========================================================================================
' frmOptionsEditor_Show
' ========================================================================================
'Function frmOptionsEditor_Show( ByVal hWndParent As HWnd, _
' ByVal nCmdShow As Long = 0 _
' ) As Long
Function frmOptionsEditor_Show( ByVal pWindow AS CWindow PTR) As Long
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)
pWindow->AddControl("LABEL", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_LBLKEYWORDCASE, "Case:", 167, 273, 34, 16, _
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("COMBOBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_COMBOCASE, "", 208, 269, 125, 22, _
WS_CHILD Or WS_VISIBLE Or WS_VSCROLL Or WS_TABSTOP Or CBS_DROPDOWNLIST, _
WS_EX_CLIENTEDGE Or WS_EX_LEFT Or WS_EX_LTRREADING Or WS_EX_RIGHTSCROLLBAR)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKCODETIPS, "Enable CodeTips", 0, 21, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKSHOWLEFTMARGIN, "Show left margin", 185, 0, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKSYNTAXHIGHLIGHTING, "Syntax highlighting", 0, 0, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKCURRENTLINE, "Highlight current line", 0, 63, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKLINENUMBERING, "Show line numbers", 185, 42, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKCONFINECARET, "Confine caret to text", 0, 42, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("LABEL", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_LBLLOCALIZATION, "English.lang", 14, 217, 206, 22, _
WS_CHILD Or WS_VISIBLE Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN Or SS_CENTER Or SS_CENTERIMAGE Or SS_NOTIFY, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("BUTTON", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CMDLOCALIZATION, "Select", 255, 214, 69, 26, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_PUSHBUTTON Or BS_NOTIFY Or BS_CENTER Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("GROUPBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_FRAMELOCALIZATION, "Localization", 0, 198, 333, 50, _
WS_CHILD Or WS_VISIBLE Or BS_TEXT Or BS_LEFT Or BS_NOTIFY Or BS_GROUPBOX, _
WS_EX_TRANSPARENT Or WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKTABTOSPACES, "Treat Tab as spaces", 0, 83, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKMULTIPLEINSTANCES, "Allow multiple instances", 0, 104, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKAUTOINDENTATION, "Auto indentation", 0, 124, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKSHOWFOLDMARGIN, "Show fold margin", 185, 21, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKCOMPILEAUTOSAVE, "Autosave files before compiling", 0, 144, 235, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
pWindow->AddControl("CHECKBOX", pWindow->hWindow, IDC_FRMOPTIONSEDITOR_CHKINDENTGUIDES, "Show Indentation guides", 185, 64, 179, 20, _
WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or BS_TEXT Or BS_NOTIFY Or BS_AUTOCHECKBOX Or BS_LEFT Or BS_VCENTER, _
WS_EX_LEFT Or WS_EX_LTRREADING)
Function = 0
End Function
it works.
I have suspected that something was wrong (with the compiler?) playing with my tab control example.
If I do this, it works fine
' // Create the first tab page
DIM pTabPage1 AS CTabPage PTR = NEW CTabPage
pTabPage1->SetFont("", 14, FW_BOLD)
pTabPage1->InsertPage(hTab, 0, "Tab 1", -1, @TabPage1_WndProc)
' // Create the second tab page
DIM pTabPage2 AS CTabPage PTR = NEW CTabPage
pTabPage2->SetFont("", 12, FW_BOLD)
pTabPage2->InsertPage(hTab, 1, "Tab 2", -1, @TabPage2_WndProc)
But I did a mistake and instead of pTabPage2->SetFont("", 12, FW_BOLD), I used pTabPage1->SetFont("", 12, FW_BOLD)
' // Create the first tab page
DIM pTabPage1 AS CTabPage PTR = NEW CTabPage
pTabPage1->SetFont("", 14, FW_BOLD)
pTabPage1->InsertPage(hTab, 0, "Tab 1", -1, @TabPage1_WndProc)
' // Create the second tab page
DIM pTabPage2 AS CTabPage PTR = NEW CTabPage
pTabPage1->SetFont("", 12, FW_BOLD)
pTabPage2->InsertPage(hTab, 1, "Tab 2", -1, @TabPage2_WndProc)
and then it happened the same that with your code.
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.
> 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.
Quote from: Jose Roca on June 02, 2016, 03:07: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.
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
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.
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.
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.
{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.
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.
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.
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
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.
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.
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.
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.
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.
I have a little ways to go before I get Scintilla integrated. Working of the configuration files. Got it loading and saving and populating all of the Environment Options dialogs. Just need to ensure that I am handling the unicode WSTRING stuff correctly. I wish FB had a native dynamic WSTRING.