Re: The 1001 questions about vbRichClient5 (2019-05-09)
Originally Posted by jpbro
Olaf - thank you very much for the clarifications re: cThreadHandler, very informative.
I just tried your threaded cActiveScript approach on Windows 10.1809 and it worked flawlessly when compiled, but I get the following error on Terminate in the IDE (maybe this is normal in the IDE?):
Code:
Run-time error '453':
Error Calling: Run()
ThreadError: Can't find DLL entry point AtlAxWinTerm in atl
Ah - did receive that error as well yesterday, and fixed it in the RC5-sources already ...
(AtlAxWinTerm is an inline-function and not a public export in the atl.dll)
What if you replace (in cScriptThread Class_Initialize) a new Cleanup-Script:
Code:
.Add "Sub Cleanup()" 'needed and called shortly before Thread-Termination
.Add " On Error Resume Next"
.Add " New_c.CleanupRichClientDll"
.Add " If Err Then Err.Clear"
.Add "End Sub"
Re: The 1001 questions about vbRichClient5 (2019-05-17)
If Not TH. WaitForEmpty JobQueue (15) = True Then'over 15S automatically clears all
TH. Cancel Execution
Else
End If
If the thread executes for a long time, is the main program hung up and waited for 15S to execute again? If so, it is equivalent to blocking mode, which will affect the mouse click interface response. I used to use the following methods, there is no difference between the two methods, thank you.
Dim tAddTickCount As Long, tTickCount As Long
TAddTickCount = 15
TTickCount = New_c.HPTimer
Do
New_c.SleepEx 10
DoEvents
If TH.WaitForEmpty JobQueue = True Then Exit Do
If New_c.HPTimer - tTickCount > tAddTickCount Then
Re: The 1001 questions about vbRichClient5 (2019-05-09)
Originally Posted by jpbro
Unfortunately that change did not seem to help in IDE mode - not a big deal if it's fixed in RC5 already for the next update though.
Just restored my older RC5-Binary from last week...
and with the changed Class_Terminate below it works for me now in the IDE...
(suppressing the unwanted error-bubbling from the TH.Cleanup-call)
Code:
Private Sub Class_Terminate()
On Error Resume Next
Set tmrState = Nothing
CancelFlag = True
If Not TH.WaitForEmptyJobQueue(10) Then TH.CancelExecution
TH.CallSynchronous "Run", "Cleanup"
Set TH = Nothing
On Error GoTo 0
End Sub
The above should work with all older RC5-versions.
Nevertheless I've uploaded a new RC5-Binary now to the usual place...
Re: The 1001 questions about vbRichClient5 (2019-05-17)
Originally Posted by yinxiaodan
If Not TH. WaitForEmpty JobQueue (15) = True Then...
You can also write the above this way:
Code:
'wait for max 15 seconds, then cancel the Job-Execution in case the wait-procedure was not successful (returned False)
If TH.WaitForEmptyJobQueue(15) = False Then TH.CancelExecution
And when written that way - it will do basically the same thing, you've tried to implement by hand in your follow-up code-snippet.
The Function-Signature for cThreadHandler.WaitForEmptyJobQueue is this one:
(as e.g. Intellisense will show you - but also the VB6-IDE-ObjectExplorer):
Code:
Public Function WaitForEmptyJobQueue(Optional ByVal WaitMaxSeconds As Double = 3) As Boolean
Note, that the above contains an Optional Param which is named WaitMaxSeconds (with a default at 3seconds).
The Max-part should tell you, that only in case the JobQueue will not fall back to zero within that time, it will wait "to the max".
If the JobQueueCount reaches zero earlier than in the given WaitMaxSeconds-Param, the Function will return earlier of course (with True).
As for "blocking the main-thread" - I'm not sure where you see a problem...
Because normally you want your already running thread, to finish its job.
And a Job is finished, when you receive the TH_MethodFinished-Event.
Normally the WaitForEmptyJobQueue-call only comes into play, when you want to shutdown your App (with a potentially still running thread-job).
Re: The 1001 questions about vbRichClient5 (2019-05-26)
Q#20: No ... (but via JScript + cActiveScript there's a workaround - see below)
Q#21:
- JavaScript is supported in two modes (first Lang-String-param of the New_c.ActiveScript-constructor)
1) "JScript" (the old classic MS-JScript-interpreter, which works also on older systems)
2) "JScript9" (the much faster JS-engine, which came on systems with IE9 and higher)
cActiveScript implements the IActiveScripting interfaces directly - it is in many parts compatible to the MS-ScriptControl,
but implements a few extra-things like EventBinding and others...
New_c.ActiveScript() with no optional Params given will use the defaults and return a "VBScript"-Scripting-instance:
- with the RC5 cConstructor and cCairo instances available directly within ScriptCode as usual via New_c and Cairo
- with all VbRuntime Consts and Enums available in ScriptCode
- with all RC5-Consts and Enums available in ScriptCode
New_c.ActiveScript("JScript") does the same as the above (New_c and Cairo available in JScript-Code)
New_c.ActiveScript("JScript9") ... dito - but with the JScript9 engine
If one does not need RC5-Objects or VBRuntime+RC5-constants in JScript- or JScript9- mode (which is usually the case),
the instancing lines should be: New_c.ActiveScript("JScript", False, False) or New_c.ActiveScript("JScript9", False, False) respectively...
Here an example, which does RegEx-stuff using the JScript(9) engines:
Code:
Option Explicit
Private WithEvents SC As cActiveScript, CO As Object
Private Sub Form_Load()
Set SC = New_c.ActiveScript("JScript", False, False)
' Set SC = New_c.ActiveScript("JScript9", False, False) '<- this should work on Vista+-machines as well
SC.AddCode "function RegExReplace(s, pat, srepl) {" & vbCrLf & _
" var re = new RegExp(pat, 'g')" & vbCrLf & _
" return s.replace(re, srepl)" & vbCrLf & _
"}"
SC.AddCode "function RegExMatch(s, pat) {" & vbCrLf & _
" var re = new RegExp(pat, 'g')" & vbCrLf & _
" return s.match(re)" & vbCrLf & _
"}"
Set CO = SC.CodeObject 'calls work fastest, when we use the CodeObject
End Sub
'convenience-wrappers around (latebound) calls of the CodeObject
Function RegExReplace(S As String, Pat As String, sRepl As String) As String
RegExReplace = CO.RegExReplace(S, Pat, sRepl)
End Function
Function RegExMatch(S As String, Pat As String) As String
RegExMatch = CO.RegExMatch(S, Pat)
End Function
Private Sub Form_Click()
On Error Resume Next
'replace all "special chars" and "all Number-Digits"
Debug.Print RegExReplace("abc._*_+_?_^_$_{_}_(_)_|_[_\123xyz", "[.*+?^${}|()\\\[\]]|[0-9]", "")
'switch words
Debug.Print RegExReplace("John Doe", "(\w+)\s(\w+)", "$2, $1")
Dim Match 'simple Word-Matcher
For Each Match In Split(RegExMatch("John Doe", "(\w+)"), ",")
Debug.Print Match
Next
If Err Then Debug.Print Err.Description
End Sub
Private Sub SC_error(Description As String, ByVal LineNr As Long, ByVal CharPos As Long)
If Len(Description) Then Debug.Print "Error in Line: " & LineNr & "-Pos: " & CharPos & " -> " & Description
End Sub
HTH
Olaf
Last edited by Schmidt; May 26th, 2019 at 12:16 PM.
Re: The 1001 questions about vbRichClient5 (2019-05-26)
Hi Olaf. I tested your code and RC5.ActiveScript implements the RegExp operation very well, thank you very much.
But JScript doesn't seem to support some JavaScript functions, for example: String.fromCodePoint
I executed the following JavaScript code with ActiveScript but it didn't work:
JavaScript Code:
function escapeVal(str) {
return str.replace(/&#([0-9]+);/g, function (_, m0) {
return String.fromCodePoint(parseInt(m0, 10));
}).replace(/&#x([0-9a-f]+);/g, function (_, m0) {
return String.fromCodePoint(parseInt(m0, 16));
}).replace(/&|<|>|"|'/g, function (_) {
switch (_) {
case '&': return '&';
case '<': return '<';
case '>': return '>';
case '"': return '"';
case ''': return '\'';
}
return _;
});
}
RC5.ActiveScript prompts the following error message:
Error in Line: 3-Pos: 9 -> Object does not support the "fromCodePoint" property or method
Method 'escapeVal' of object 'JScriptTypeInfo' failed
The test code is as follows:
Code:
Option Explicit
Private WithEvents SC As cActiveScript, CO As Object
Private Sub Form_Load()
'Set SC = New_c.ActiveScript("JScript", False, False)
Set SC = New_c.ActiveScript("JScript9", False, False) '<- this should work on Vista+-machines as well
SC.AddCode GetCode_EscapeVal()
Set CO = SC.CodeObject 'calls work fastest, when we use the CodeObject
End Sub
'convenience-wrappers around (latebound) calls of the CodeObject
Private Function RegExEscapeVal(S As String) As String
RegExEscapeVal = CO.escapeVal(S)
End Function
Private Function GetCode_EscapeVal() As String
With New_c.StringBuilder
.AppendNL "function escapeVal(str) {"
.AppendNL " return str.replace(/&#([0-9]+);/g, function (_, m0) {"
.AppendNL " return String.fromCodePoint(parseInt(m0, 10));"
.AppendNL " }).replace(/&#x([0-9a-f]+);/g, function (_, m0) {"
.AppendNL " return String.fromCodePoint(parseInt(m0, 16));"
.AppendNL " }).replace(/&|<|>|"|'/g, function (_) {"
.AppendNL " switch (_) {"
.AppendNL " case '&': return '&';"
.AppendNL " case '<': return '<';"
.AppendNL " case '>': return '>';"
.AppendNL " case '"': return '" & Chr(34) & "';"
.AppendNL " case ''': return '\'';"
.AppendNL " }"
.AppendNL " return _;"
.AppendNL " });"
.AppendNL "}"
GetCode_EscapeVal = .ToString
End With
End Function
Private Sub Form_Click()
Const TEST_STRING = "&#" & "72" & ";" & "&#" & "101" & ";" & "&#" & "108" & ";" & "&#" & "108" & ";" & "&#" & "111" & ";" & "&#" & "20320" & ";" & "&#" & "22909" & ";"
On Error Resume Next
MsgBox RegExEscapeVal(TEST_STRING)
If Err Then Debug.Print Err.Description
End Sub
Private Sub SC_error(Description As String, ByVal LineNr As Long, ByVal CharPos As Long)
If Len(Description) Then Debug.Print "Error in Line: " & LineNr & "-Pos: " & CharPos & " -> " & Description
End Sub
Last edited by dreammanor; May 26th, 2019 at 10:56 PM.
Re: The 1001 questions about vbRichClient5 (2019-05-26)
Originally Posted by dreammanor
Hi Olaf. I tested your code and RC5.ActiveScript implements the RegExp operation very well, thank you very much.
But JScript doesn't seem to support some JavaScript functions, for example: String.fromCodePoint
Well, that's why so called PolyFills (just google the term) exists, which beam the js-Versions of older Browsers into the "new age"...
Please make no mistake - even the newer (and quite fast) JScript9-engine is old (in comparison to V12 or Mozillas-JSengine).
Though for the isolated case above, you can do manually, what Polyfills ensure on a "grander scale" within older Browsers...
just add the missing Method to the global String-Object of the js-engine beforehand:
Code:
With New_c.StringBuilder
.AppendNL "String.fromCodePoint = function(x){"
.AppendNL " var code, elements = [];"
.AppendNL " for (var i = 0; i < arguments.length; i++){"
.AppendNL " code = +arguments[i];"
.AppendNL " elements.push(code < 0x10000"
.AppendNL " ? String.fromCharCode(code)"
.AppendNL " : String.fromCharCode(((code -= 0x10000) >> 10) + 0xD800, code % 0x400 + 0xDC00)"
.AppendNL " );"
.AppendNL " } return elements.join('')"
.AppendNL "}"
SC.AddCode .ToString
End With
Re: The 1001 questions about vbRichClient5 (2019-05-26)
Excellent solution !
I used to be reluctant to use VBScript and JScript because they don't support the latest JS functions and syntax. Now I can boldly use VBScript (JScript) and RC5.ActiveScript. Thank you very much, Olaf.
Qustion 022: Can RC5.ActiveScript implement JavaScript debugging?
Qustion 022: Can RC5.ActiveScript implement JavaScript debugging?
Currently JavaScript debugging is mainly done in the browser, which is very inconvenient. Can RC5.ActiveScript add some features to debug JavaScript? E.g: AddBreakpoint, ClearBreakpoints, and debugging related events. Thanks.
Last edited by dreammanor; Jun 12th, 2019 at 04:24 AM.
Question 023: cWidgets.LoadFromXML cannot load custom control cwShape
Question 023: cWidgets.LoadFromXML cannot load custom control cwShape
In my FormDesigner, if the name of the custom control is cwTextBox, cWidgets.LoadFromXML can load the control. If the control name is cwShape, cWidgets.LoadFromXML cannot load this control. What is the reason for this? Thanks.
Note:
I didn't use vbWidgets.dll
Last edited by dreammanor; Jul 15th, 2019 at 08:03 PM.
Question 024: Looking for advice: Develop a simple HtmlEditor with RC5
Question 024: Looking for advice: Develop a simple HtmlEditor with RC5
I need to develop a simple HtmlEditor (or RichTextBox) with RC5, which only needs to handle font styles (FontSize, FontBold, FontColor, FontUnderline, FontItalic, line-spacing), no need to process images and tables.
I'd like to get some helpful suggestions, thank you!
Last edited by dreammanor; Jul 15th, 2019 at 08:10 PM.
Re: Question 023: cWidgets.LoadFromXML cannot load custom control cwShape
Originally Posted by dreammanor
Question 023: cWidgets.LoadFromXML cannot load custom control cwShape
In my FormDesigner, if the name of the custom control is cwTextBox, cWidgets.LoadFromXML can load the control.
If the control name is cwShape, cWidgets.LoadFromXML cannot load this control. What is the reason for this? Thanks.
As it is currently, neither of your two (Project-Private cw-Classes) is loaded from XML (albeit the saving worked correctly)...
What you see as "loaded cwTextBox" is indeed a cwTextBox, but the Class-instance was "drawn" from your registered vbWidgets.dll (check it out, you can type in it)...
Whereas cwShape is not a known ClassName in vbWidgets.dll - hence no loading from there...
To influence the XML-Loading-behaviour (which by default looks for Widget-ClassNames only in vbWidgets.dll),
you will have to use the IWidgetLoader-interface, which the RC5 exports.
I've seen, that you attempted to instantiate IWidgetLoader - but since it's prefixed with an "I" and not a "c", it wants to be implemented instead.
Here the adapted cfMain-Code from your zipped Sources (note the additional Lines, I've marked in blue)
Code:
Option Explicit
Public WithEvents Form As cWidgetForm, WithEvents Page As cWidgetForm
Public PageWidthInch As Double, PageHeightInch As Double
Public WithEvents BtnLoad As cwButton, WithEvents BtnSave As cwButton
Implements IWidgetLoader
Private Function IWidgetLoader_CreateWidget(TypeName As String) As Object
Select Case LCase$(TypeName)
Case "cwtextbox": Set IWidgetLoader_CreateWidget = New cwTextBox
Case "cwshape": Set IWidgetLoader_CreateWidget = New cwShape
End Select
End Function
Private Sub BtnLoad_Click()
Dim sFile As String: sFile = App.Path & "\Page1.xml"
If New_c.FSO.FileExists(sFile) Then
Page.Widgets.RemoveAll
Page.Widgets.LoadFromXML New_c.FSO.ReadByteContent(sFile), Me
Page.Refresh
End If
End Sub
Private Sub BtnSave_Click()
Dim sFile As String: sFile = App.Path & "\Page1.xml"
New_c.FSO.WriteByteContent sFile, Page.Widgets.SerializeToXML(True)
End Sub
Private Sub Class_Initialize()
Set Form = Cairo.WidgetForms.Create(vbSizable, "Shape-Handling at constant 96dpi (Page=8.5x11 inch)", True, 1024, 768)
Form.SetMinMaxDimensions 720, 560
Form.IconImageKey = "frmIco" 'ensure a Form-Icon per ImageList-Key (Icon was loaded in Sub Main)
Form.WidgetRoot.BackColor = &H888888
PageWidthInch = 8.5: PageHeightInch = 11 'let's define an absolute Page-Size
Set Page = Cairo.WidgetForms.CreateChild(Form.hWnd)
Page.WidgetRoot.BackColor = vbWhite
Page.WidgetRoot.DesignMode = True
Page.WidgetRoot.DesignModeGridWidth = 4
End Sub
Private Sub Form_Load() 'shape-coords are absolute inches
AddNewShape "S1", 0.5, 0.5, 2, 1
AddNewShape "S2", 2, 2, 2, 1
AddNewShape "S3", 3.5, 3.5, 2, 1
AddNewTextBox "T1", 0.5, 5, 2, 1
AddNewTextBox "T2", 2, 6.5, 2, 1
AddNewTextBox "T3", 3.5, 8, 2, 1
Set BtnSave = Form.Widgets.Add(New cwButton, "BtnSave", 16, 8, 160, 24)
BtnSave.Caption = "Save to XML"
Set BtnLoad = Form.Widgets.Add(New cwButton, "BtnLoad", 16, 40, 160, 24)
BtnLoad.Caption = "Load From XML"
End Sub
Private Sub Form_ResizeWithDimensions(ByVal NewWidth As Long, ByVal NewHeight As Long)
Dim x, y, dx, dy
Cairo.CalcAspectFit PageWidthInch / PageHeightInch, NewWidth, NewHeight, x, y, dx, dy, 20
Page.Move x, y, dx, dy
End Sub
Private Sub Page_ResizeWithDimensions(ByVal NewWidth As Long, ByVal NewHeight As Long)
Page.WidgetRoot.Zoom = NewWidth / (PageWidthInch * 96)
End Sub
Private Sub AddNewShape(Name As String, x, y, dx, dy) 'coords in inches
Dim NewWidget As cwShape
Set NewWidget = Page.Widgets.Add(New cwShape, Name, x * 96, y * 96, dx * 96, dy * 96)
End Sub
Private Sub AddNewTextBox(Name As String, x, y, dx, dy) 'coords in inches
Dim NewWidget As cwTextBox
Set NewWidget = Page.Widgets.Add(New cwTextBox, Name, x * 96, y * 96, dx * 96, dy * 96)
End Sub
So, if you want to get serious with a Form-Designer, a proper implementation of IWidgetLoader is mandatory.
I'd also suggest to implement IWidgetLoader in its own Loader-Class(es)... since this will allow you later,
to pass different ones to the XML-Loading-Routine (dependent on context).
These different Loaders could be named e.g. cLoadWidgetsRuntime, cLoadWidgetsDesignTime, cLoadWidgetsDeployedRegfree).
You get the idea, I think...
Olaf
Last edited by Schmidt; Jul 16th, 2019 at 01:23 AM.
Re: Question 024: Looking for advice: Develop a simple HtmlEditor with RC5
Originally Posted by dreammanor
Question 024: Looking for advice: Develop a simple HtmlEditor with RC5
I need to develop a simple HtmlEditor (or RichTextBox) with RC5, which only needs to handle font styles (FontSize, FontBold, FontColor, FontUnderline, FontItalic, line-spacing), no need to process images and tables.
I'd like to get some helpful suggestions, thank you!
I thought I've given advice in this regard already (several times).
Use one of the larger JS-frameworks, stick with it - and learn how to use it...
(my recommendation is still the same: OpenUI5, sine it is the most VB6-like usable, compared to the alternatives).
And if you do that (working with one of the larger JS-frameworks), HTML-editing is not in the picture anymore -
you do not see (or need) any HTML-code at all - all you need to work with, is the JS-code, which addresses the Framework in question.
And in case of OpenUI5, these JS-code-lines (which "address the Framework") are really quite similar to "loading Widgets" (or Controls).
You can write a (very very simple) "translator", which is putting these Control-adding JS-Lines out with ease (e.g. from a DB, which stored a certain arrangement of those Control-defs)
There is no complex syntax-parser needed for that.
Please look again at the fiddle I've posted some time ago in #261 of this thread: http://www.vbforums.com/showthread.p...=1#post5349003
And then really *play-around-with-it* - there's really only a handful of codelines to understand.
OpenUI5 is really nice and relatively easy (compared to the alternatives) - it is open-sourced, but actively maintained by SAP-developers -
about 100 Controls to choose from - most of them working on both - Desktop- and Mobile-Browsers (usually those in the sap.m Namespace).
Re: Question 023: cWidgets.LoadFromXML cannot load custom control cwShape
Originally Posted by Schmidt
As it is currently, neither of your two (Project-Private cw-Classes) is loaded from XML (albeit the saving worked correctly)...
What you see as "loaded cwTextBox" is indeed a cwTextBox, but the Class-instance was "drawn" from your registered vbWidgets.dll (check it out, you can type in it)...
Whereas cwShape is not a known ClassName in vbWidgets.dll - hence no loading from there...
To influence the XML-Loading-behaviour (which by default looks for Widget-ClassNames only in vbWidgets.dll),
you will have to use the IWidgetLoader-interface, which the RC5 exports.
I've seen, that you attempted to instantiate IWidgetLoader - but since it's prefixed with an "I" and not a "c", it wants to be implemented instead.
Here the adapted cfMain-Code from your zipped Sources (note the additional Lines, I've marked in blue)
Code:
Option Explicit
Public WithEvents Form As cWidgetForm, WithEvents Page As cWidgetForm
Public PageWidthInch As Double, PageHeightInch As Double
Public WithEvents BtnLoad As cwButton, WithEvents BtnSave As cwButton
Implements IWidgetLoader
Private Function IWidgetLoader_CreateWidget(TypeName As String) As Object
Select Case LCase$(TypeName)
Case "cwtextbox": Set IWidgetLoader_CreateWidget = New cwTextBox
Case "cwshape": Set IWidgetLoader_CreateWidget = New cwShape
End Select
End Function
Private Sub BtnLoad_Click()
Dim sFile As String: sFile = App.Path & "\Page1.xml"
If New_c.FSO.FileExists(sFile) Then
Page.Widgets.RemoveAll
Page.Widgets.LoadFromXML New_c.FSO.ReadByteContent(sFile), Me
Page.Refresh
End If
End Sub
Private Sub BtnSave_Click()
Dim sFile As String: sFile = App.Path & "\Page1.xml"
New_c.FSO.WriteByteContent sFile, Page.Widgets.SerializeToXML(True)
End Sub
Private Sub Class_Initialize()
Set Form = Cairo.WidgetForms.Create(vbSizable, "Shape-Handling at constant 96dpi (Page=8.5x11 inch)", True, 1024, 768)
Form.SetMinMaxDimensions 720, 560
Form.IconImageKey = "frmIco" 'ensure a Form-Icon per ImageList-Key (Icon was loaded in Sub Main)
Form.WidgetRoot.BackColor = &H888888
PageWidthInch = 8.5: PageHeightInch = 11 'let's define an absolute Page-Size
Set Page = Cairo.WidgetForms.CreateChild(Form.hWnd)
Page.WidgetRoot.BackColor = vbWhite
Page.WidgetRoot.DesignMode = True
Page.WidgetRoot.DesignModeGridWidth = 4
End Sub
Private Sub Form_Load() 'shape-coords are absolute inches
AddNewShape "S1", 0.5, 0.5, 2, 1
AddNewShape "S2", 2, 2, 2, 1
AddNewShape "S3", 3.5, 3.5, 2, 1
AddNewTextBox "T1", 0.5, 5, 2, 1
AddNewTextBox "T2", 2, 6.5, 2, 1
AddNewTextBox "T3", 3.5, 8, 2, 1
Set BtnSave = Form.Widgets.Add(New cwButton, "BtnSave", 16, 8, 160, 24)
BtnSave.Caption = "Save to XML"
Set BtnLoad = Form.Widgets.Add(New cwButton, "BtnLoad", 16, 40, 160, 24)
BtnLoad.Caption = "Load From XML"
End Sub
Private Sub Form_ResizeWithDimensions(ByVal NewWidth As Long, ByVal NewHeight As Long)
Dim x, y, dx, dy
Cairo.CalcAspectFit PageWidthInch / PageHeightInch, NewWidth, NewHeight, x, y, dx, dy, 20
Page.Move x, y, dx, dy
End Sub
Private Sub Page_ResizeWithDimensions(ByVal NewWidth As Long, ByVal NewHeight As Long)
Page.WidgetRoot.Zoom = NewWidth / (PageWidthInch * 96)
End Sub
Private Sub AddNewShape(Name As String, x, y, dx, dy) 'coords in inches
Dim NewWidget As cwShape
Set NewWidget = Page.Widgets.Add(New cwShape, Name, x * 96, y * 96, dx * 96, dy * 96)
End Sub
Private Sub AddNewTextBox(Name As String, x, y, dx, dy) 'coords in inches
Dim NewWidget As cwTextBox
Set NewWidget = Page.Widgets.Add(New cwTextBox, Name, x * 96, y * 96, dx * 96, dy * 96)
End Sub
So, if you want to get serious with a Form-Designer, a proper implementation of IWidgetLoader is mandatory.
I'd also suggest to implement IWidgetLoader in its own Loader-Class(es)... since this will allow you later,
to pass different ones to the XML-Loading-Routine (dependent on context).
These different Loaders could be named e.g. cLoadWidgetsRuntime, cLoadWidgetsDesignTime, cLoadWidgetsDeployedRegfree).
You get the idea, I think...
Olaf
Hi Olaf, after using IWidgetLoader-interface, everything is OK now, thank you very much.
Re: Question 024: Looking for advice: Develop a simple HtmlEditor with RC5
Originally Posted by Schmidt
I thought I've given advice in this regard already (several times).
Use one of the larger JS-frameworks, stick with it - and learn how to use it...
(my recommendation is still the same: OpenUI5, sine it is the most VB6-like usable, compared to the alternatives).
And if you do that (working with one of the larger JS-frameworks), HTML-editing is not in the picture anymore -
you do not see (or need) any HTML-code at all - all you need to work with, is the JS-code, which addresses the Framework in question.
And in case of OpenUI5, these JS-code-lines (which "address the Framework") are really quite similar to "loading Widgets" (or Controls).
You can write a (very very simple) "translator", which is putting these Control-adding JS-Lines out with ease (e.g. from a DB, which stored a certain arrangement of those Control-defs)
There is no complex syntax-parser needed for that.
Please look again at the fiddle I've posted some time ago in #261 of this thread: http://www.vbforums.com/showthread.p...=1#post5349003
And then really *play-around-with-it* - there's really only a handful of codelines to understand.
OpenUI5 is really nice and relatively easy (compared to the alternatives) - it is open-sourced, but actively maintained by SAP-developers -
about 100 Controls to choose from - most of them working on both - Desktop- and Mobile-Browsers (usually those in the sap.m Namespace).
HTH
Olaf
Yes, I'm going to use OpenUI5 in my next development project (converting my old VB6 enterprise apps to SPAs).
Now I'm still developing my WebBuilder. My FormDesigner is actually a Web-Page-Builder, which allows users to drag web page components with mouse to complete the design of a web page. I don't know if OpenUI5 could do this kind of work.
Last edited by dreammanor; Jul 17th, 2019 at 04:04 AM.
Re: Question 024: Looking for advice: Develop a simple HtmlEditor with RC5
Originally Posted by dreammanor
...My FormDesigner is actually a Web-Page-Builder,
which allows users to drag web page components with mouse to complete the design of a web page.
I don't know if OpenUI5 could do this kind of work.
I'm not sure, whether you *want* to design WebPages this way ...
(by dragging components or Dom-Nodes around using "free, absolute Pixel-Positioning").
A modern web-page (no matter if SinglePage-App or "just a normal one"),
needs to work on "all screens, all sizes" (plus support for the horizontal or vertical flip-modes, mobile devices allow).
Classic "VB6-like" Form-Design is not really working for these highly dynamic GUI-scenarios
(it can be achieved of course, when you introduce Layout-Classes - but as soon as you
introduce such classes, your "pixel-exact Form-Designer" will not be needed anymore -
and has to be re-written around those Layout-Classes (with a completely different Designer-approach).
But to answer your question...
Yes, OpenUI5 contains a HTML-Control, which integrates into a given SPA-layout as a rectangle you can influence (size-wise).
And within that "small or midsized" HTML-container-rect, you can then still support databinding,
but have more "freedom of movement" inside that Client-Rect (with your "normal HTML-nodes").
Re: Question 024: Looking for advice: Develop a simple HtmlEditor with RC5
Originally Posted by Schmidt
I'm not sure, whether you *want* to design WebPages this way ...
(by dragging components or Dom-Nodes around using "free, absolute Pixel-Positioning").
A modern web-page (no matter if SinglePage-App or "just a normal one"),
needs to work on "all screens, all sizes" (plus support for the horizontal or vertical flip-modes, mobile devices allow).
Classic "VB6-like" Form-Design is not really working for these highly dynamic GUI-scenarios
(it can be achieved of course, when you introduce Layout-Classes - but as soon as you
introduce such classes, your "pixel-exact Form-Designer" will not be needed anymore -
and has to be re-written around those Layout-Classes (with a completely different Designer-approach).
Yes, what you said is very reasonable. Currently, my WebBuilder provides three designers: WebForm-Designer, FlexBox-Designer, and CssGrid-Designer, where WebForm-Designer uses "free, absolute Pixel-Positioning". I want to make WebForm-Designer as a complement to the other two designers.
Originally Posted by Schmidt
But to answer your question...
Yes, OpenUI5 contains a HTML-Control, which integrates into a given SPA-layout as a rectangle you can influence (size-wise).
And within that "small or midsized" HTML-container-rect, you can then still support databinding,
but have more "freedom of movement" inside that Client-Rect (with your "normal HTML-nodes").
The knowledge you provide is very important to me. My WebBuilder will be ready for a few weeks. After I complete the WebBuilder, I'll delve into OpenUI5, thank you very much, Olaf.
Last edited by dreammanor; Jul 18th, 2019 at 02:16 AM.
Question 025: Does cWebKit.Document support ExecCommand like VB.WebBrowser?
Question 025: Does cWebKit.Document support ExecCommand like VB.WebBrowser?
VB.WebBrowser supports ExecCommand, QueryCommandSupported, QueryCommandValue and other commands. I'd like to know if cWebKit.Document supports those commands? Thanks.
Last edited by dreammanor; Jul 28th, 2019 at 08:07 AM.
The VB.WebBrowser.ExecCommand does not support the useCSS and styleWidthCSS commands, so I want to try ClEditor in cWebKit. Now the ClEditor editing window can be successfully displayed in the cwBrowser window, but the ToolStrip is not displayed and the font styles cannot be set.
My WebApp directory is as follows:
\WebApp\WebRoot\images
\WebApp\WebRoot\index.html
\WebApp\WebRoot\jquery.cleditor.css
\WebApp\WebRoot\jquery.cleditor.js
\WebApp\WebRoot\jquery.cleditor.min.js
Re: The 1001 questions about vbRichClient5 (2019-07-28)
You don't need the WebServer-instance, to make that work.
Here some code, which will work on an empty (normal) VB-Form -
only a reference to vbWidgets and vbRichClient5 is required:
Code:
Option Explicit
Private WithEvents Panel As cWidgetForm, WithEvents WB As cwBrowser
Private Sub Form_Load()
Set Panel = Cairo.WidgetForms.CreateChild(hWnd)
Set WB = Panel.Widgets.Add(New cwBrowser, "WB")
WB.WebKit.Navigate2 "file:///" & Replace(App.Path & "\CLEditor\index.html", "\", "/")
End Sub
Private Sub Form_Resize()
ScaleMode = vbPixels
Panel.Move 0, 0, ScaleWidth, ScaleHeight
End Sub
Private Sub Panel_ResizeWithDimensions(ByVal NewWidth As Long, ByVal NewHeight As Long)
WB.Widget.Move -1, -1, NewWidth + 3, NewHeight
End Sub
The magenta-colored part is the important one...
(a SubFolder, named \CLEditor sits below the App-Path, and contains the unzipped CLEditor-package).
Re: The 1001 questions about vbRichClient5 (2019-07-28)
Originally Posted by Schmidt
You don't need the WebServer-instance, to make that work.
Here some code, which will work on an empty (normal) VB-Form -
only a reference to vbWidgets and vbRichClient5 is required:
Code:
Option Explicit
Private WithEvents Panel As cWidgetForm, WithEvents WB As cwBrowser
Private Sub Form_Load()
Set Panel = Cairo.WidgetForms.CreateChild(hWnd)
Set WB = Panel.Widgets.Add(New cwBrowser, "WB")
WB.WebKit.Navigate2 "file:///" & Replace(App.Path & "\CLEditor\index.html", "\", "/")
End Sub
Private Sub Form_Resize()
ScaleMode = vbPixels
Panel.Move 0, 0, ScaleWidth, ScaleHeight
End Sub
Private Sub Panel_ResizeWithDimensions(ByVal NewWidth As Long, ByVal NewHeight As Long)
WB.Widget.Move -1, -1, NewWidth + 3, NewHeight
End Sub
The magenta-colored part is the important one...
(a SubFolder, named \CLEditor sits below the App-Path, and contains the unzipped CLEditor-package).
Question 027: cWidgets.LoadFromXML cannot load custom properties in binary mode
Question 027: cWidgets.LoadFromXML cannot load custom properties after compiling into exe
In VB6-IDE, cWidgets.LoadFromXML can successfully load the custom property MyCaption from the XML file. But when the source code is compiled into an exe, cWidgets.LoadFromXML cannot load the custom property MyCaption from the XML file. I don't know why?
Re: The 1001 questions about vbRichClient5 (2019-08-04)
I tried your demo (looking pretty nice if I may add) and all I can say so far is that I have reproduced the problem when the app is compiled, not sure why it is happening though. I put a MsgBox in the cwShape.MyCaption Property Let method and the property doesn't get set at all when compiled.
Re: The 1001 questions about vbRichClient5 (2019-08-04)
I'm not at the bottom of it yet, but I see your MyCaption property has a "DT_" prefix in the XML file, which indicates it is a "design-time" property. That might explain why it doesn't load in the compiled version, but I'm not yet familiar enough with the RC5 widgets to know how to change the property to a run-time available one yet. I'm investigating...
Re: The 1001 questions about vbRichClient5 (2019-08-04)
I see the RC5 WidgetBase object has a RuntimePropertiesCommaSeparated property. I've tried setting this in the cwShape.Class_Initialize event as follows:
Code:
w.RuntimePropertiesCommaSeparated "MyCaption"
But now the MyCaption property isn't serialized at all. I'm too inexperienced with the RC5 Widget engine TBH, so perhaps Olaf is your best bet here, but I will continue experimenting.
Re: The 1001 questions about vbRichClient5 (2019-08-04)
The reason it does not work compiled is, that Project-Private WidgetClasses (currently!) cannot be enumerated
(Property-wise, via the RC5.cProps/cProp stuff which uses TypelibInformation-APIs),
when the VB6-IDE "is not around" (to provide those for Project-Private COM-Classes).
So, if one wants to use the builtin "Auto-Property XML-serialization" (where your own Props are prefixed with "DT_" in the XML-stream), one has to implement his own Widget-Classes in his own ActiveX-Dll - these would work in IDE-mode, but also compiled.
I'd think, that despite this little flaw, the Auto-XML-serialization is still a nice feature,
since it does not require any explicit "ReadProperties/WriteProperties"-fiddling, as seen with VB6 old UserControls.
This should make it easier (implementation-wise) for future contributors to the Widget-Control-Stack.
As for the W.RuntimePropertiesCommaSeparated ...
This gives a Developer the chance, to ease the burden of the XML-AutoSerializer
(by providing a Name-List of Public Props, which are either too complex to be serialized,
or don't make any sense to be serialized, because they are only useful to set at runtime).
Re: The 1001 questions about vbRichClient5 (2019-08-04)
Originally Posted by jpbro
I tried your demo (looking pretty nice if I may add) and all I can say so far is that I have reproduced the problem when the app is compiled, not sure why it is happening though. I put a MsgBox in the cwShape.MyCaption Property Let method and the property doesn't get set at all when compiled.
Originally Posted by jpbro
I'm not at the bottom of it yet, but I see your MyCaption property has a "DT_" prefix in the XML file, which indicates it is a "design-time" property. That might explain why it doesn't load in the compiled version, but I'm not yet familiar enough with the RC5 widgets to know how to change the property to a run-time available one yet. I'm investigating...
Originally Posted by jpbro
I see the RC5 WidgetBase object has a RuntimePropertiesCommaSeparated property. I've tried setting this in the cwShape.Class_Initialize event as follows:
Code:
w.RuntimePropertiesCommaSeparated "MyCaption"
But now the MyCaption property isn't serialized at all. I'm too inexperienced with the RC5 Widget engine TBH, so perhaps Olaf is your best bet here, but I will continue experimenting.
Hi jpbro, glad to see you, thanks for investigation and experiment. I'm trying to handwrite an XMLPropertyBag to store RC5 Widgets properties.
Re: The 1001 questions about vbRichClient5 (2019-08-04)
Originally Posted by Schmidt
The reason it does not work compiled is, that Project-Private WidgetClasses (currently!) cannot be enumerated
(Property-wise, via the RC5.cProps/cProp stuff which uses TypelibInformation-APIs),
when the VB6-IDE "is not around" (to provide those for Project-Private COM-Classes).
So, if one wants to use the builtin "Auto-Property XML-serialization" (where your own Props are prefixed with "DT_" in the XML-stream), one has to implement his own Widget-Classes in his own ActiveX-Dll - these would work in IDE-mode, but also compiled.
I'd think, that despite this little flaw, the Auto-XML-serialization is still a nice feature,
since it does not require any explicit "ReadProperties/WriteProperties"-fiddling, as seen with VB6 old UserControls.
This should make it easier (implementation-wise) for future contributors to the Widget-Control-Stack.
As for the W.RuntimePropertiesCommaSeparated ...
This gives a Developer the chance, to ease the burden of the XML-AutoSerializer
(by providing a Name-List of Public Props, which are either too complex to be serialized,
or don't make any sense to be serialized, because they are only useful to set at runtime).
HTH
Olaf
Understand. I'm trying to handwrite an XMLPropertyBag to store RC5 Widgets properties. Thank you, Olaf.
Edit:
If LoadFromXML can read some of the preset properties (for example: Tag, XmlTag, JsonTag, BinaryTag, etc.), it will be extremely convenient for RC5 developers. If so, I can save the custom attribute in XmlTag, JsonTag or BinaryTag.
Last edited by dreammanor; Aug 9th, 2019 at 04:59 AM.
Re: The 1001 questions about vbRichClient5 (2019-08-04)
Below is how to use the RC5 subclasser, taken from another thread. I thought it good to place here as well.
The following simple example (MouseEnter/MouseLeave) shows its usage ...
Code:
Option Explicit
Private Declare Function TrackMouseEvent& Lib "user32" (lpTrack As Any)
Private WithEvents SC As cSubClass, PB As VB.PictureBox
Private Sub Form_Load()
Set PB = Controls.Add("VB.PictureBox", "PB"): PB.Visible = True
Set SC = New_c.SubClass: SC.Hook PB.hWnd
End Sub
Private Sub SC_WindowProc(Result As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long)
Const WM_MOUSEMOVE = &H200, WM_MOUSELEAVE = &H2A3
Select Case Msg
Case WM_MOUSEMOVE: HandleMouseEnterOn PB 'handle the mouse move with our own code
Case WM_MOUSELEAVE: HandleMouseLeaveOn PB 'handle the mouse leave with our own code
End Select
Result = SC.CallWindowProc(Msg, wParam, lParam) 'allow the default message handling. if you don't want this to happen, Exit Sub before this.
End Sub
Private Sub HandleMouseEnterOn(Ctl As Object)
Dim T&(0 To 3): T(0) = 16: T(1) = 2: T(2) = Ctl.hWnd
TrackMouseEvent T(0)
Ctl.BackColor = vbGreen
End Sub
Private Sub HandleMouseLeaveOn(Ctl As Object)
Ctl.BackColor = vbRed
End Sub
Question 028: CC.GetTextExtents cannot calculate the width of Chinese characters
Question 028: CC.GetTextExtents cannot calculate the width of Chinese characters
If the font is "Arial", CC.GetTextExtents can correctly calculate the width of the Chinese character.
However, if the font is "MS Sans Serif", CC.GetTextExtents cannot correctly calculate the width of Chinese characters.
Code:
Option Explicit
Public Function GetTextExtends(ByVal Text As String, ByRef FontHeight As Double, _
FontName As String, FontSize As Double, _
Optional Bold As Boolean, Optional Italic As Boolean, _
Optional Underline As Boolean, Optional StrikeThrough As Boolean) As Double
Dim Srf As cCairoSurface
Dim CC As cCairoContext
Set Srf = Cairo.CreateSurface(1, 1)
Set CC = Srf.CreateContext()
If FontName <> vbNullString And FontSize > 0 Then
CC.SelectFont FontName, FontSize, , Bold, Italic, Underline, StrikeThrough
End If
'GetTextExtends = CC.GetTextExtentPtr(StrPtr(Text), Len(Text))
GetTextExtends = CC.GetTextExtents(Text, FontHeight)
End Function
Re: The 1001 questions about vbRichClient5 (2019-08-14)
hi dreammanor
do you think other people can add questions about vbRichClient here? (or you prefer to keep it some kind of your?)
because I wanted to ask for a fairly simple one.
[If you prefer me not do it here anymore (or that I do it using some particular manner/format) let me know]
Ok, my question:
Wich is the best/fastest way to draw on a cCairoSurface an OutLine text ? (maybe using DrawText)
Re: The 1001 questions about vbRichClient5 (2019-08-14)
I'm not sure if this is the best/fastest way, but you can call DrawText with the PathOnly parameter = True, then call Stroke to draw the outline. E.g. (where "c" is a CCairoContext object):
Re: The 1001 questions about vbRichClient5 (2019-08-14)
Originally Posted by jpbro
I'm not sure if this is the best/fastest way, but you can call DrawText with the PathOnly parameter = True, then call Stroke to draw the outline. E.g. (where "c" is a CCairoContext object):
...
Thank you!
I just came to same solution. First tried pathonly=true, but nothing appeared so then I used "stroke" and it worked.
... but to me seems not well Antialiased... maybe I'm wrong.
Re: The 1001 questions about vbRichClient5 (2019-08-14)
Originally Posted by reexre
... but to me seems not well Antialiased... maybe I'm wrong.
Hmm...it looks decently antialiased to me, but you (being a graphics expert) would have a better idea of what is "well" antialiased than I do. Maybe you could try setting the CairoContext.AntiAlias property to CAIRO_ANTIALIAS_SUBPIXEL to see if that looks better?