Re: The 1001 questions about vbRichClient5 (2019-08-14)
You may also want to play with the .SetLineCap and .SetLineJoin values for the context - these can make a difference, too.
Also, a lot of my older RC5 projects have the line cairo.FontOptions=CAIRO_ANTIALIAS_DEFAULT somewhere in them, immediately after instantiating Cairo. For reasons I never quite understood (given that I was, apparently, setting to its default value!), it seemed like I always needed that to get nice font rendering.
Perhaps Olaf would care to comment?
If you don't know where you're going, any road will take you there...
Re: The 1001 questions about vbRichClient5 (2019-08-14)
Originally Posted by ColinE66
You may also want to play with the .SetLineCap and .SetLineJoin values for the context - these can make a difference, too.
Also, a lot of my older RC5 projects have the line cairo.FontOptions=CAIRO_ANTIALIAS_DEFAULT somewhere in them, immediately after instantiating Cairo. For reasons I never quite understood (given that I was, apparently, setting to its default value!), it seemed like I always needed that to get nice font rendering.
Perhaps Olaf would care to comment?
The enum-values of cairo_antialias_enum (although numbering 4)
are only 3 distinct values really - in the older cairo-version I use...
(because enum-value CAIRO_ANTIALIAS_DEFAULT means the same thing as CAIRO_ANTIALIAS_GRAY)
There's two Properties one can assign this enum to - and:
Cairo.FontOptions = cairo_antialias_enum
...affects different things, compared to...
CC.Antialias = cairo_antialias_enum
The Cairo.FontOptions are for "true Text-Rendering" only - and its 3 distinct enum-settings will be applied only,
in case the CC.TextOut or CC.DrawText were called without the optional PathOnly-Parameter.
Here Cairo.FontOptions = CAIRO_ANTIALIAS_SUBPIXEL ist the mode with the highest quality in "true TextOutput mode"
(it will render Texts using Windows-Cleartype in that mode, making use of the LCD-subpixels)
In the other case... if a PathOnly-Boolean-Parameter was given with True,
then the TextOutput is not using "real Font-Rendering" anymore,
but falls back to "normal Cairo-Path-Rendering" (like any other Line- or Arc, or other Drawing-Primitive call).
The advantage in PathOnly-mode is, that Text-placements - are then done with true SubPixel-precision
(regarding the Character-Offsets, which is not the case in ClearType-Fontrendering-mode -
in ClearType-mode the TextChars have to be "placed at hard PixelBoundaries", to make ClearType possible at all).
So, the CC.Antialias-Setting is only influencing Cairos "normal Pathed-Output-Mode"
(curves, lines, rectangles, etc. as well as "TextPaths").
Re: The 1001 questions about vbRichClient5 (2019-08-14)
Thanks for that explanation, Olaf - that certainly clears-up a few things for me. When you talk about Text-placements and Offsets, does this have a bearing on the return values from GetTextExtents, by any chance? I ask because, recently, I had a situation whereby I was only ever seeing whole numbers when measuring character widths, and was expecting some decimal precision.
If you don't know where you're going, any road will take you there...
Re: The 1001 questions about vbRichClient5 (2019-08-14)
Originally Posted by ColinE66
Thanks for that explanation, Olaf - that certainly clears-up a few things for me. When you talk about Text-placements and Offsets, does this have a bearing on the return values from GetTextExtents, by any chance? I ask because, recently, I had a situation whereby I was only ever seeing whole numbers when measuring character widths, and was expecting some decimal precision.
Yep, GetTextExtents tends to delivers "whole numbers",
when CC.SelectFont was using a Font with a "normal size" (8-25pt),
and when no CC.ScaleDrawings was in place (the Scale still being at their default-factor 1).
If you *use* Path-based Textrendering calls (with the PathOnly-Param at True),
then you can (shortly before the Stroke, or Fill - where the Path is still "active" and not closed),
do something like that for precise path-measurement:
Code:
Dim X1#, Y1#, X2#, Y2#
CC.GetPathExtents X1, Y1, X2, Y2
Debug.Print X1, X2, X2 - X1 'shows X1, X2 and the X-Distance
Re: The 1001 questions about vbRichClient5 (2019-08-14)
Originally Posted by reexre
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)
Hi reexre, all questions about RC5 are welcome.
My intention is to give RC5 developers a convenient place to ask questions and discuss. I've added your question to the question list in the post #1.
Re: The 1001 questions about vbRichClient5 (2019-08-19)
Although this question has nothing to do with VB6 and RC5, I'm learning and using JS with the thinking of an old VB6 user, so I still want to put it in the VB6 sub-forum. I'd like to hear the opinions from Olaf, jpbro and other JS experts.
I saw a piece of JavaScript code and I thought it was a bit weird.
Code:
var myBox = new box();
function box() {
this.dx = 0;
this.dy = 0;
this.test = function(a, b, c){
var div = box.test2(a, b, c);
if (div) {
myBox.dx = 400;
myBox.dy = 600;
}
}
this.test2 = function(a, b, c) {
...
...
}
}
I understand this code this way: box is a function object(class), and variable myBox is an instance of the box object(class). But the myBox variable appears inside the box, which makes me feel a bit strange.
Is this usage of myBox appropriate? Will skilled or sophisticated JavaScript developers write code in this way? Is there a better way to achieve similar functionality? Thanks.
Re: The 1001 questions about vbRichClient5 (2019-08-19)
This is not weird but pretty common. Consider this VB6 code in an empty Std-EXE project
thinBasic Code:
Option Explicit
Private Sub Form_Load()
Form1.Caption = "Test"
End Sub
Form1 is the default (hidden) instance of Form1 class which gets used/references *inside* the very same class. Just make sure it's initialized before accessing it (at runtime, line position of the code does not matter). In this case VB runtime makes sure it's dimensioned and instantiated before our caption assignment is reached.
Re: The 1001 questions about vbRichClient5 (2019-08-19)
Originally Posted by wqweto
This is not weird but pretty common. Consider this VB6 code in an empty Std-EXE project
thinBasic Code:
Option Explicit
Private Sub Form_Load()
Form1.Caption = "Test"
End Sub
Form1 is the default (hidden) instance of Form1 class which gets used/references *inside* the very same class. Just make sure it's initialized before accessing it (at runtime, line position of the code does not matter). In this case VB runtime makes sure it's dimensioned and instantiated before our caption assignment is reached.
cheers,
</wqw>
Hi wqweto, what you said is very reasonable.
IMO, "Form1.Caption = "Test"" has two purposes:
(1) For simplicity and convenience
(2) convenient for novices to learn
But for experienced VB6 developers, they might prefer to write: Me.Caption = "Test"
Szlamany suggested that I replace "dm" or "cmn" with "this" (IMO, "this" of JS is similar to "Me" of VB6). My reply to this is as follows:
I also considered replacing the class instance variable "dm" or "cmn" with "this". But I found a phenomenon, that is, the class instance variable "dm" or "cmn" seems to be more readable than "this", especially in the messy JS code. Because I can think of "dm" or "cmn" as a global variable, just like the global variables of VB6.
Also, I'd like to know if there is a more standard and more elegant JS code style.
Last edited by dreammanor; Oct 23rd, 2019 at 01:54 AM.
Re: The 1001 questions about vbRichClient5 (2019-08-19)
Referencing Form1 instead of acting on current instance through Me keyword (or omitting it altogether) fails the moment a second instance of the form is needed.
If you plan on directly using dm, cmn, whatever instead of this you should probably make sure your singletons are not instantiated second time (not sure how to do this in JS) by accident.
Re: The 1001 questions about vbRichClient5 (2019-08-19)
Originally Posted by wqweto
Referencing Form1 instead of acting on current instance through Me keyword (or omitting it altogether) fails the moment a second instance of the form is needed.
If you plan on directly using dm, cmn, whatever instead of this you should probably make sure your singletons are not instantiated second time (not sure how to do this in JS) by accident.
cheers,
</wqw>
Yes. But there seems to be no way to ensure that the Class can only be instantiated once. One way szlamany mentioned is to make the necessary explanations/comments when declaring the dm or cmn variable.
Re: The 1001 questions about vbRichClient5 (2019-08-19)
Originally Posted by dreammanor
Yes. But there seems to be no way to ensure that the Class can only be instantiated once. One way szlamany mentioned is to make the necessary explanations/comments when declaring the dm or cmn variable.
You could always raise an error (in the constructor-function), when the outside (global) reference was already set on the window-object:
Code:
var cmn = new cmnc(); // only for this line, the constructor-function will reach the "success" alert-msg
var cmn2 = new cmnc(); // here the error will be thrown, when you look into the console
function cmnc() {
if (cmn) throw "cmn was already instantiated"
this.BdX = 0
this.BdY = 0
alert("success") // just to show, that we reached the end of the constructor
}
BTW - I've noticed, you're trying a different js-Framework currently (from APNSoft)...
Nothing wrong with that, if you want to learn more about JavaScript "generally"...
Though my recommendation still stands (OpenUI5, which you "promised to look into")...
I did not give this recommendation lightly - you know... (tested nearly "everything else" beforehand ... angular, react, etc.)...
And nothing comes even near the ease of use of OpenUI5
(which is especially strong with "JSON-model-bindings" and responsive rendering on mobile-devices).
Here is, how this SPA (Single-Page-Application) will look on an iPhone (in normal, vertical view):
And here, how the same SPA wil re-render itself, when you rotate the device horizontally:
JavaScript-Code-wise the amount of App-Code one has to write, is ridiculously small (less than 30 lines in App.js, which is listed below):
Code:
varApp, Page1;
varCore=sap.ui.getCore() //just a shortcut to the Core-Object of the framework
Core.attachInit(main) //call the main()-routine, after the Core finished initializing
functionmain(){
Core.setModel(newsap.ui.model.json.JSONModel({})) //init the global Model
App=newsap.m.App() //init the App
Page1=NewProductsPage("/Products") //create a new Products-Page
App.addPage(Page1) //add this new Page to the App
App.placeAt("content") //render the App at the usual content-div
}
functionNewProductsPage(dsPath){
varPage=newsap.m.Page()
Page.dsPath=dsPath
RPC("/asp/JSONQuery.asp", {SQL:"Select ProductName, QuantityPerUnit, UnitPrice, UnitsInStock, Discontinued From Products"}, function(Res){
Res.RowIdx=Res.RecordCount?1:0//enhance the RPC-Result-JSON-Object about a RowIdx-Property (and intialize it)
M(dsPath, Res) //make the JSON-Result known as the datasource in our Model M (under the given dsPath)
Page.setCustomHeader(newsap.m.Bar({design:"Header"}).addContentMiddle(newsap.m.Text({text:"Products ({"+dsPath+"/RowIdx} / {"+dsPath+"/RecordCount})"})))
varForm=newsap.ui.layout.form.SimpleForm({labelMinWidth:160, width:"calc(80% + 70px)", editable:true})
AddLabeledCtlTo( Form, "Productname", newsap.m.Input ({value:"{0}", liveChange:ValUpd}), 1, 3)
AddLabeledCtlTo( Form, "Quantity per Unit", newsap.m.Input ({value:"{1}", liveChange:ValUpd}), 1, 3)
AddLabeledCtlTo( Form, "Unit price", newsap.m.Input ({value:"{2}", liveChange:ValUpd}), 1, 3)
AddLabeledCtlTo( Form, "Units in stock", newsap.m.Input ({value:"{3}", liveChange:ValUpd}), 1, 3)
AddLabeledCtlTo( Form, "Discontinued", newsap.m.Switch({state:"{4}", customTextOn:"Yes", customTextOff:"No"}), 1, 3)
Page.addContent(Form)
Page.setFooter(NewDataCtlBar(Form, dsPath))
})
returnPage
}
This is achieved (as said) due to the databinding-capabilities of the framework (which work over the curly-braces you see in the code above).
The bottom-control in the Page-Footer comes from a constructor-function (NewDataCtlBar), which encapsulates several other Controls in an "ADODC-like"-behaving way...
How much code do you think you'd have to write, to re-implement your own ADODC-like UserControl in VB6?
Well, here is the JS-Code which does exactly that, using OpenUI5-Controls (about 20 lines):
This code is contained (together with 5 other, much smaller Helper-Function) in the only other js-File of the App
(named Global.js - but you can study the sources of all "Browser-delivered files", when you switch your Browser to "View-Source"-Mode).
Well, here's hope, that this little "DB-Table-Viewer-App" (Table Products from SQLite-hosted NWind.db) is encouraging.
And as said, the code is not even "reduced to the max" + much of it could be auto-generated directly at the serverside via VB6-Code in a COM-Dll.
Re: The 1001 questions about vbRichClient5 (2019-08-19)
Hi Olaf, your example is always amazing. I value your opinions very much. In most cases, your suggestions are what I think are "the best solution", as is OpenUI5.
Learning and using SPA and OpenUI5 is my next step (second step plan) and my most important plan, I'll put all my energy into it.
WebSite-Builder is my first step plan and is the ongoing plan. My WebSite-Builder was suspended for 2 months due to other delays. Now I need to continue to complete it.
My WebSite-Builder requires a visual MenuBuilder. Initially, I was planning to use a pure CSS menu builder solution. But pure JS MenuBuilder seems to have more flexibility. So I found CommonMenu.JS on the Internet, I want to understand its principles and logic, and then write my own pure JS MenuBuilder.
My JS skills are very poor. The biggest obstacle I faced was that I couldn't debug JS efficiently. I only know that debugging JS in Chrome, which is extremely inconvenient. So I have been trying to write a JS debugging tool like the VB6 IDE (there is no progress yet).
I can use VB6 to develop extremely complex desktop software, one of the big reasons is that VB6 debugging is very convenient. This is also why the Spread control, which is very complicated to DaveDavis, is just a small control for me.
Since I can't debug JS as well as VB6, the development of my pure JS MenuBuilder is very slow. But I believe I can finish it. I would be grateful if you could give me some advice in this regard.
After completing my WebSite-Builder, I'll devote all my time and energy to learning and using OpenUI5 and SPA.
Last edited by dreammanor; Oct 24th, 2019 at 04:09 AM.
Qustion 031: An error occurred while deleting a control in the FormDesigner
Qustion 031: An error occurred while deleting a control in the FormDesigner
(1) Select one of the controls in the FormDesigner and click the Remove button to delete the selected control. Then, click on the Remove button again and the system will crash. That is, when a certain control is deleted, if no other controls are selected, a reference to the Page.ActiveWidget will result in an error ("If Not Page.ActiveWidget Is Nothing Then" will cause an error). The error code is as follows:
Code:
Private Sub BtnRemove_Click()
If Not Page.ActiveWidget Is Nothing Then
Page.Widgets.Remove Page.ActiveWidget.Key
Page.Refresh
End If
End Sub
((2) If the control(Sender) is deleted in the BubblingEvent, the system will crash. The error code is as follows:
Code:
Private Sub Form_BubblingEvent(Sender As Object, EventName As String, P1 As Variant, P2 As Variant, P3 As Variant, P4 As Variant, P5 As Variant, P6 As Variant, P7 As Variant)
If EventName = "W_KeyDown" Then
If P1 = vbKeyDelete Then
Page.Widgets.Remove Sender.Widget.Key
Page.Refresh
End If
End If
End Sub
Last edited by dreammanor; Nov 4th, 2019 at 04:39 PM.
Re: Qustion 032: A very interesting Color-Wheel from Adobe
Originally Posted by ColinE66
Wow. That is really cool. And far more creative than mine - mine is nothing special
Ten years ago, I spent a lot of time researching the drawing skills of vb controls, and also collected a lot of very good code, but I haven't developed owner-draw /custom-draw controls for a long time, and now I've completely forgotten those cumbersome drawing operations. I remember that I found a similar example of the Adobe Color Wheel in PsCode, and I'm trying to search it out.
Re: Qustion 031: An error occurred while deleting a control in the FormDesigner
Originally Posted by dreammanor
Qustion 031: An error occurred while deleting a control in the FormDesigner
(1) Select one of the controls in the FormDesigner and click the Remove button to delete the selected control. Then, click on the Remove button again and the system will crash. That is, when a certain control is deleted, if no other controls are selected, a reference to the Page.ActiveWidget will result in an error ("If Not Page.ActiveWidget Is Nothing Then" will cause an error). The error code is as follows:
I've uploaded a new version with a fix for that behaviour (which only happens when in cWidgetRoot.DesignMode = True).
Aside from that, the .ActiveWidget Property should not really be used, when in Designmode
(it is for "normal mode" and indicates the Widget which "has focus" or "can get KeyBoard-Input").
Better would be (which would have avoided the error) to use the Selection-Properties of the WIdgetRoot,
as this code shows (which supports also the deletion of multiple selected Widgets):
Code:
Private Sub BtnRemove_Click()
DeleteSelectionOn Page.WidgetRoot
' If Not Page.ActiveWidget Is Nothing Then
' Page.Widgets.Remove Page.ActiveWidget.Key
' Page.Refresh
' End If
' Page.Refresh
End Sub
Private Sub DeleteSelectionOn(Root As cWidgetRoot)
Dim i As Long
For i = 0 To Root.SelectedWidgets.Count - 1
Root.SelectParent.Widgets.Remove Root.SelectedWidgets.KeyByIndex(i)
Next
Root.Refresh
End Sub
Re: The 1001 questions about vbRichClient5 (2019-11-07)
Much appreciated, Olaf. I've used the latest RC5 dll and the problems are completely solved.
In addition, in the design window of the VB6 IDE, right-click on a control, and the control is also selected while popping up the right-click menu. However, in RC5 FormDesigner, I can't select the currently clicked control with the right mouse button.
Re: The 1001 questions about vbRichClient5 (2019-11-07)
Originally Posted by dreammanor
In addition, in the design window of the VB6 IDE, right-click on a control, and the control is also selected while popping up the right-click menu.
However, in RC5 FormDesigner, I can't select the currently clicked control with the right mouse button.
I've deliberately left this out "for the User to implement" (because of the several possibilities, what one might want to do with previously selected Widgets)...
The Bubbling-Event of the Page-Object (not the Form-Object) would be the right place, to catch the right MouseClick...
E.g. implementing a scenario, where the User discards a pre-existing selection, in case the new clicked Widget is not part of the currently selected Group:
Code:
Private Sub Page_BubblingEvent(Sender As Object, EventName As String, P1 As Variant, P2 As Variant, P3 As Variant, P4 As Variant, P5 As Variant, P6 As Variant, P7 As Variant)
If EventName = "W_MouseUp" Then
If P1 = vbRightButton Then
Dim W As cWidgetBase: Set W = Sender.Widget
If Not W.Root.SelectedWidgets.Exists(W.Key) Then 'if the Sender is currently not part of the Selection, we remove the entire Selection
Set W.Root.SelectParent = Nothing: W.Root.SelectedWidgets.RemoveAll
End If
If W.Root.SelectedWidgets.Count = 0 Then 'when no Selection exists, we add the Sender to it
Set W.Root.SelectParent = W.Parent: W.Root.SelectedWidgets.Add W.Key
End If
Page.Refresh
'now one can show a Popup here (using the current Selection-Infos in SelectParent and SelectedWidgets as a Context)
Form.Caption = "Current Selection on " & W.Root.SelectParent.Key & " contains " & W.Root.SelectedWidgets.Count & " Widgets"
End If
End If
End Sub
Qustion 033: How to create a "two-orientation" LinearPattern?
Qustion 033: How to create a "two-orientation" LinearPattern?
Under Olaf's patient guidance, I can finally draw a adobe-like ColorWheel with Cario. But my method is a bit complicated, I'd like to know if there is an easier way.
If a "two-orientation" LinearPattern could be implemented/created, the drawing of the ColorWheel will become very simple.
The meaning of "two-orientation" LinearPattern is this:
(1) Horizontal gradient (AddColorStop) has 6 colors: vbRed, vbYellow, vbGreen, vbCyan, vbBlue, vbMagenta, vbRed
(2) Vertical gradient (AddColorStop) has two colors: vbWhite, the above horizontal color
Here's the code to draw the Color Wheel:
Code:
Option Explicit
Private Sub Form_Load()
Dim ColorStops 'define the Colors the "Conical-Gradient will span and interpolate-between"
ColorStops = Array(vbRed, vbYellow, vbGreen, vbCyan, vbBlue, vbMagenta, vbRed)
Set Picture = CreateCircleSrf(200, 0, 100, ColorStops).Picture
End Sub
Function CreateCircleSrf(Size, RadiusInner, RadiusOuter, ColorStops) As cCairoSurface
Dim Steps As Long, Pat As cCairoPattern, Pat2 As cCairoPattern, i As Long
Dim TmpSrf As cCairoSurface, ColorBytes() As Byte, nColor As Long, nIdx As Long
Steps = 2 * Cairo.PI * RadiusOuter 'calculate the amount of pixel-steps on the outer radius (2*PI*r)
'create a linear (horizontal) gradient-pattern that matches the amount of "unrolled outer-ring-pixel-steps"
Set Pat = Cairo.CreateLinearPattern(0, 0, Steps, 0)
For i = 0 To UBound(ColorStops) 'now add the Color-Stops for this gradient-pattern (to interpolate between)
Pat.AddColorStop i / UBound(ColorStops), ColorStops(i)
Next
Set TmpSrf = Cairo.CreateSurface(Steps, 1)
TmpSrf.CreateContext.Paint 1, Pat.This
TmpSrf.BindToArray ColorBytes
Set CreateCircleSrf = Cairo.CreateSurface(Size, Size) 'create the return-value of this function
With CreateCircleSrf.CreateContext 'now we can enter drawing-mode on the Srf-Context
.SetLineCap CAIRO_LINE_CAP_ROUND 'for softer "overlapped-blending" at the line-"corner"-endpoints
.SetLineWidth 1.8 '1.8 'oversize the drawn lines for a little bit of overlap (0.9px to the left and right)
.TranslateDrawings Size / 2, Size / 2 'shift the Contexts Coord-Sys into the center of the Srf
For i = 1 To Steps 'now we "walk the outer ring" (rotating a little bit after each step)
.MoveTo 0, RadiusOuter - .GetLineWidth
.LineTo 0, RadiusInner + .GetLineWidth
nIdx = i - 1
nColor = RGB(ColorBytes(nIdx * 4 + 2, 0), ColorBytes(nIdx * 4 + 1, 0), ColorBytes(nIdx * 4, 0))
Set Pat2 = Cairo.CreateLinearPattern(0, 0, 0, RadiusOuter)
Pat2.AddColorStop 0, vbWhite
Pat2.AddColorStop 1, nColor
.Stroke 0, Pat2 '<- Stroke the line with the current Gradient-Pattern-Color (at the current Pattern-Coord-Pos)
'this prepares the two Coord-Systems for the next round of our loop...
.RotateDrawingsDeg 360 / Steps 'increase the rotation-angle on the Context-CoordSys for our next line-drawing
Next
End With
TmpSrf.ReleaseArray ColorBytes
End Function
Last edited by dreammanor; Nov 11th, 2019 at 10:35 PM.
Qustion 034: How to use RC5.WebKit to display images from RC5.WebArchive in web pages
Qustion 034: How to use RC5.WebKit to display image resources from RC5.WebArchive in web pages?
I want to "preview" dynamically generated HTML pages with RC5.WebKit, and the images in the web pages come from RC5.WebArchive (for example: _FontAwesomeSVGs.wac).
I'd like to know: Can RC5.WebKit read resources from RC5.WebArchive and pass them to HTML pages? Thanks!
Qustion 035: How does RC5.ActiveScript use third-party JavaScript libs?
Qustion 035: How does RC5.ActiveScript use third-party JavaScript libs?
I need to parse JavaScript code into AST (JSON string) using acorn (a tiny, fast JavaScript parser)and put it into the database, or use UglifyJS to compress my JavaScript code. I wonder if RC5.ActiveScript can use third-party JavaScript libs. Thanks!
Re: The 1001 questions about vbRichClient5 (2019-12-05)
Hi all vbRichClient Experts...
I am currently trying to develop a stand-alone application using VB6, SQLite, VbRichClient5 and MSHFlexgrid.
So far everything is going well, but something bothers me, where all the data displayed on MSHFlexgrid is truncated, and only a maximum of 40 characters is displayed.
Out of curiosity I tried to replace the DataGrid in SQLiteDemos (NWind-Demo) with MSHFlexgrid, and it turned out the same, all the data that appeared on MSHFlexgrid was truncated (only 40 characters are displayed).
I ask for your help to be able to help resolve this issue.
Re: The 1001 questions about vbRichClient5 (2019-12-05)
Hi truerad21, try the following code:
Code:
Private Sub Form_Load()
If CreateConnection Then
Dim recSet As cRecordset
Dim SQLStr As String
SQLStr = "select * from vi_sample"
Set recSet = DBConn.OpenRecordset(SQLStr, True)
If recSet.RecordCount <> 0 Then
Set MSHFlexGrid1.DataSource = recSet.GetADORsFromContent.DataSource
End If
End If
End Sub
Note:
Note: The above code does not need to explicitly (early) reference the Microsoft ActiveX Data Objects Library.
Last edited by dreammanor; Dec 10th, 2019 at 08:08 PM.
Re: The 1001 questions about vbRichClient5 (2019-12-05)
Originally Posted by truerad21
Out of curiosity I tried to replace the DataGrid in SQLiteDemos (NWind-Demo) with MSHFlexgrid, and it turned out the same, all the data that appeared on MSHFlexgrid was truncated (only 40 characters are displayed).
For ADO-based DataBinding, the RC5.cRecordset can:
- either return a "full, freestanding ADO-Recordset" (as a copy of the cRecordsets content, as dreammanor pointed out already)...
- or you can use the cRecordset.Datasource, which implements the "OleDB-SimpleProvider" under the covers
In the latter mode, no copy of the cRecordset-content is made - and only this mode supports "changes on the Rs in Write-Direction" (when they were made on the Grid).
Not sure, why the MSHFlexGrid-DataSource-Interface does cut String-Fields off at a certain boundary (the VB6-DataGrid does not show these issues).
Both databinding-modes are requiring MS-ADO-libs (under the cover of the cRecordset) to accomplish the ADO-Binding,
so the purpose of "using SQLite instead of ADO/JET" is somewhat "torpedoed", when such ADO-Bindings are used.
Better would be, to use Grid-Bindings which do not require any MS-libs - and there's Grids out there which support such things...
(for example the ComponentOne-vsFlexGrids support IFlexDataSource-interfaces)
The above Grid is quite stable in the meantime - can be deployed regfree - and one will not need any MS-ADO-based Binding-Mechanisms,
to visualize external DataContainers or Recordsets...(since it supports the IVBFlexDataSource-interface)
Qustion 036: About RC5.WebKit.Document.callWebScriptMethod
Qustion 036: About RC5.WebKit.Document.callWebScriptMethod
On XP, RC5.WebKit has better compatibility than IE, so I always use RC5.WebKit instead of IE. Now, I need to get the return value of JavaScript through RC5.WebKit.Document.callWebScriptMethod. My code is as follows:
Code:
Option Explicit
Private wk As cWebKit
Private Sub Form_Load()
Dim Doc As WebKit.IDOMDocument, sHtml As String
InitBrowser "about:blank"
Set Doc = wk.Document
'sHtml = "<script>function myReflectFunc(sParam){return sParam}</script>"
sHtml = "<!DOCTYPE html><head><script>function myReflectFunc(sParam){return sParam}</script></head>" & _
"<html><body style='font-family:Arial;font-size:10pt'>%%</body></html>"
'Doc.Write sHtml
'Doc.setTextContent sHtml
wk.LoadHTMLString sHtml
'and then call them conveniently via jsCallFunc(FuncName, ParamArray)
MsgBox jsCallFunc("myReflectFunc", "Hello World")
End Sub
Sub InitBrowser(Optional URL As String = "about:blank")
Set wk = New_c.WebKit(True, "C:\Program Files\Microsoft Visual Studio\VB98\MyResources\WebKitCairo")
wk.InitializeView Me.hWnd, 0, 0, 480, 320
wk.Navigate2 URL
End Sub
Function jsCallFunc(FuncName As String, ParamArray P())
Dim i As Long, nCount As Long, args As Variant
Dim Doc As WebKit.IDOMDocument
args = Array()
nCount = UBound(P) + 1
If nCount > 0 Then
ReDim Preserve args(nCount - 1)
For i = 0 To nCount - 1
args(i) = P(i)
Next i
End If
Set Doc = wk.Document
jsCallFunc = Doc.callWebScriptMethod(FuncName, args, nCount)
End Function
When executing "Doc.callWebScriptMethod (FuncName, args, nCount)", the system prompts an error:
"Object doesn't support this action"
I'd like to know if my code is wrong, thanks!
Last edited by dreammanor; Dec 19th, 2019 at 09:54 PM.
Re: The 1001 questions about vbRichClient5 (2019-12-19)
I also tested WebView and it still doesn't seem to work:
Code:
......
......
Dim WV As WebKit.WebView
Set WV = wk.WebView
jsCallFunc = WV.windowScriptObject.callWebScriptMethod(FuncName, args, nCount)
OR
Code:
......
......
Dim WV As WebKit.WebView, SO As IWebScriptObject
Set WV = wk.WebView
Set SO = WV.windowScriptObject
jsCallFunc = SO.callWebScriptMethod(FuncName, args, nCount)
Last edited by dreammanor; Dec 20th, 2019 at 09:17 AM.
Re: Qustion 036: About RC5.WebKit.Document.callWebScriptMethod
Originally Posted by dreammanor
... I need to get the return value of JavaScript through RC5.WebKit.Document.callWebScriptMethod.
Not all of the WebKit-Typelibs interfaces-methods are implemented (within the C++ representation of the WebKit-Dll)...
and 'callWebScriptMethod' is one of them...
What I did implement (directly in cWebKit) is the two Methods 'AddScript" and 'Evaluate'.
So, with a little workaround you can do stuff like this:
Code:
Option Explicit
Private WithEvents wk As cWebKit
Private Sub Form_Load()
InitBrowser "about:blank"
Dim sHtml As String
sHtml = "<!DOCTYPE html><html><head></head><body style='font-family:Arial;font-size:10pt'>%%</body></html>"
wk.loadHTMLString sHtml
wk.AddScript "function myReflectFunc(sParam){return sParam}"
wk.AddScript "function myObjReturnFunc(P1, P2){" & _
" var o={};" & _
" o.Sum = P1+P2;" & _
" o.UTC = (new Date).toISOString(); " & _
"return JSON.stringify(o)" & _
"}"
Debug.Print jsCallFunc("myReflectFunc", "Hello World")
Debug.Print jsCallFunc("myObjReturnFunc", 1, 2)
With New_c.JSONDecodeToCollection(jsCallFunc("myObjReturnFunc", 1, 2))
Debug.Print .Prop("Sum"), .Prop("UTC")
End With
End Sub
Sub InitBrowser(Optional URL As String = "about:blank")
Set wk = New_c.WebKit(True)
wk.InitializeView Me.hWnd, 0, 0, 480, 320
wk.Navigate2 URL
End Sub
Function jsCallFunc(FuncName As String, ParamArray P()) As String
Dim i As Long, sP As String, Comma As String
For i = 0 To UBound(P)
Select Case VarType(P(i))
Case vbDouble, vbSingle: sP = sP & Comma & Str$(P(i))
Case vbString: sP = sP & Comma & "'" & P(i) & "'"
Case Else: sP = sP & Comma & P(i)
End Select
If i = 0 Then Comma = ","
Next
jsCallFunc = wk.Evaluate(FuncName & "(" & sP & ")")
End Function
'this EventHandler is necessary, to receive alert-message-strings, raised from inside Webkit-JS-Code when the alert(...)-function is called
Private Sub wk_ShowJSAlertDlg(Message As String)
Debug.Print "JS-alert: ", Message
End Sub
Re: The 1001 questions about vbRichClient5 (2019-12-19)
Hi Olaf, thank you for your detailed reply.
I tested your code and it worked fine. But I need to reference some third-party JS libs, for example: Uglifyjs.
Is it possible to load third-party JS libs using AddScript or WebArchive?
E.g:
wk.AddScript "<script src = './js/uglifyjs-test.js'> </script>"
or:
B = wa.GetContent ("./js/uglifyjs-test.js")
wk.AddScript B
My test code is as follows:
Code:
Option Explicit
Private wa As cWebArchive, WithEvents ws As cWebServer
Private WithEvents wk As cWebKit
Private Sub Form_Load()
Dim sHtml As String, B() As Byte
If App.LogMode = 0 Then 'as long as in IDE-Mode, we re-create the *.wac every time
Set wa = New_c.WebArchive
wa.ReadContentsFromDirectory App.Path & "\WebAppRoot\"
wa.SaveContentsToArchiveFile App.Path & "\WebRoot.wac"
End If
Set wa = New_c.WebArchive(App.Path & "\WebRoot.wac") 'init the WA from the *.wac-Archive-File
Set ws = New_c.WebServer 'create an InProcess-WebServer-instance
ws.Listen App.Path & "\WebAppRoot\", "127.0.0.1", 8888
InitBrowser "about:blank"
'sHtml = "<!DOCTYPE html><html><head></head><body style='font-family:Arial;font-size:10pt'>%%</body></html>"
'wk.LoadHTMLString sHtml
'wk.AddScript "<script src='./js/uglifyjs-test.js'></script>"
'B = wa.GetContent("./js/uglifyjs-test.js")
B = wa.GetContent("\js\uglifyjs-test.js")
wk.AddScript B
wk.AddScript "function TestMinify(code, options){" & _
" var result = UglifyJS.minify(code);" & _
" if (result.error) {" & _
" return result.error;" & _
" } else {" & _
" return result.code;" & _
" }" & _
"}"
Debug.Print jsCallFunc("TestMinify", "let sum = add(1, 2);function add(first, second) {return first + second;}")
End Sub
Sub InitBrowser(Optional URL As String = "about:blank")
Set wk = New_c.WebKit(True)
wk.InitializeView Me.hWnd, 0, 0, 480, 320
wk.Navigate2 URL
End Sub
Function jsCallFunc(FuncName As String, ParamArray P()) As String
Dim i As Long, sP As String, Comma As String
For i = 0 To UBound(P)
Select Case VarType(P(i))
Case vbDouble, vbSingle: sP = sP & Comma & Str$(P(i))
Case vbString: sP = sP & Comma & "'" & P(i) & "'"
Case Else: sP = sP & Comma & P(i)
End Select
If i = 0 Then Comma = ","
Next
jsCallFunc = wk.Evaluate(FuncName & "(" & sP & ")")
End Function
'this EventHandler is necessary, to receive alert-message-strings, raised from inside Webkit-JS-Code when the alert(...)-function is called
Private Sub wk_ShowJSAlertDlg(Message As String)
Debug.Print "JS-alert: ", Message
End Sub
Private Sub Command1_Click()
Dim sHtml As String, B() As Byte
sHtml = "<!DOCTYPE html><html><head></head><body style='font-family:Arial;font-size:10pt'>%%</body></html>"
wk.LoadHTMLString sHtml
'wk.AddScript "<script src='./js/uglifyjs-test.js'></script>"
'B = wa.GetContent("./js/uglifyjs-test.js")
B = wa.GetContent("\js\uglifyjs-test.js")
wk.AddScript B
wk.AddScript "function TestMinify(code, options){" & _
" var result = UglifyJS.minify(code);" & _
" if (result.error) {" & _
" return result.error;" & _
" } else {" & _
" return result.code;" & _
" }" & _
"}"
Debug.Print jsCallFunc("TestMinify", "let sum = add(1, 2);function add(first, second) {return first + second;}")
End Sub
Last edited by dreammanor; Dec 21st, 2019 at 07:50 PM.
Re: The 1001 questions about vbRichClient5 (2019-12-19)
In case the recent questions are (still) just to be able to "minify JavaScript-content",
then this is perhaps not really the ideal thread to aks about that...
Re: The 1001 questions about vbRichClient5 (2019-12-19)
Originally Posted by Schmidt
In case the recent questions are (still) just to be able to "minify JavaScript-content",
then this is perhaps not really the ideal thread to aks about that...
Question 37: How to return a string array from ActiveScript.String.split ?
Question 37: How to return an string array from ActiveScript.String.split ?
I need to use the string array returned by the ActiveScript.String.split in VB6. But ActiveScript.CodeObject seems to return only strings instead of an array, for example:
And I need to return an string array, just like VB6.Split. Thanks.
Code:
Private Sub Command1_Click()
Dim aItems As Variant
Set SC = New_c.ActiveScript("JScript9", False, False)
SC.AddCode "var aItems = 'ABCD@EFGH@IJKL'.split('@');"
Set CO = SC.CodeObject
aItems = CO.aItems
MsgBox aItems
End Sub
Last edited by dreammanor; Jan 12th, 2020 at 12:53 PM.
Re: Question 37: How to return a string array from ActiveScript.String.split ?
Originally Posted by dreammanor
Question 37: How to return an string array from ActiveScript.String.split ?
I need to use the string array returned by the ActiveScript.String.split in VB6. But ActiveScript.CodeObject seems to return only strings instead of an array, for example:
And I need to return an string array, just like VB6.Split. Thanks.
Code:
Private Sub Command1_Click()
Dim aItems As Variant
Set SC = New_c.ActiveScript("JScript9", False, False)
SC.AddCode "var aItems = 'ABCD@EFGH@IJKL'.split('@');"
Set CO = SC.CodeObject
aItems = CO.aItems
MsgBox aItems
End Sub
You are getting an JScriptTypeInfo object back that contains an JScript array. For example, calling CO.aItems.Length returns 3 as which is what you would expect as a result of the split. Problem is that you must retrieve the array elements by index, but VB6 doesn't allow you to call methods that are numbers (e.g. you can't call CO.aItems.0 to get the array item at index 0). Maybe there's a way to do this that I am unaware of, but in the meantime you can use CallByName:
Code:
MsgBox CallByName(co.aItems, "0", VbGet) ' Get array element at index 0
Re: The 1001 questions about vbRichClient5 (2020-01-12)
Hi jpbro, thank you for your reply. CallByName is an interesting method, but it seems to affect performance/speed. The reason I want to get the string array directly is to get higher performance/speed.
Re: The 1001 questions about vbRichClient5 (2020-01-12)
I'm not at all familiar with the ActiveScript stuff in RC5, so Olaf will be of more help here.
That said, I suspect that if performance is critical then interfacing with JScript9 will not be ideal. What are you trying to do in JS that can't be done in VB6? VB6 has Split, so why not do the split in VB6? Having a clearer picture of what you are trying to accomplish might help us find another more performant approach.
Re: The 1001 questions about vbRichClient5 (2020-01-12)
I need a high-performance RegExp engine, and I also need to use RegExp in Split and Replace functions, such as String.split(regExp). It seems that using JScript9 can save a lot of work, and the RegExp of JScript9 is more than 3 times faster than VBScript's.
I had planned to write a RegExp parser from scratch, but it seemed like a lot of work, so I gave up the idea.