by ZvezdanD » Sun Dec 14, 2008 5:23 pm
As some would like to say - this post is not for users but for scripters. There is not some new script, but explanation and sample code how to get listboxes and multi-line edit controls within your scripts. As you could see with the new (2.0) version of the Magic Nodes script, they are possible to get even with MM2 which don't have built-in multi-line edit control. However, my multi-line edit control is even better then MM3 built-in multi-line edit control! (I'll tell you why somewhat latter). I am sorry if there already exists some script which has something similar like my suggestion, but in that case its author also should be sorry why s/he didn't share his experience with us when we asked for such thing (there are several requests for listbox control in the Scripting Functionality Wishlist thread without any answer).
Some of us have been using some kind of workaround with Forms ActiveX which contain Listbox and Textbox (which have Multiline property), but this solution is not very well for several reasons. First of all, Forms ActiveX should be downloaded from Microsoft site if you don't have installed MS Office, then you should register it. Those controls from this ActiveX have plain old look from Win 95 days, even if you have XP or Vista. This is mostly notable on their borders and scroll bars.
Some of controls from Forms ActiveX have some drawbacks in combination with MediaMonkey, but I think that MM is guilty for this, not control itself. For example, you cannot navigate within listbox control with up and down arrow keys, because MM transfer focus to the next control like when you press Tab or Shift+Tab. I noticed strange behavior with the Textbox control when the cursor is changing between the default (pointer) shape and I-beam shape as you move the mouse over the text, but more ugly thing with the Textbox is its font setting which has an effect only on every second character (i.e. one character has specified font and the next character has default font). Fortunately, my controls don't have such issues.
Well, speaking of fonts, I come to the point when I should tell you why I think that my suggestion is even better than MM3 built-in multi-line edit control (without a fact that my suggestion works with MM2). You could guess - MM3 control don't have Font property. Well, this is not unexpected since none of MM built-in control don't have Font property. Their controls don't have Border property. Their controls don't have Background Color nor Foreground Color properties. Their multi-line edit control don't expose OnSelect event. Their multi-line edit control don't have SelectStart and SelectEnd properties. Well, neither their Edit control don't have those properties. MM developers think that we don't need to know which part of text is selected and where exactly is textual cursor, i.e. after which character. Somebody of them also should tell me why they are created a new control with a new name (Multilineedit). I would expect to get a new boolean property (Multiline) with the existing Edit control, like we have with Visual Basic and Forms Textbox controls, but not totally new control.
And now, most senseless thing about MM3 Multiline edit control - it has not scroll bars at all! Nor horizontal, nor vertical! Just type as much text as you want, but you could not get any scroll bar, neither with the new MM 3.1! Oh well. Even Visual Basic for DOS had text boxes with scroll bars. You know, with my control I could decide when and which scroll bars I want to get (overflow style).
OK, enough talk. If you don't want to go through 420 KB of source code of Magic Nodes script, here are those controls. If you are still wondering how they work, just to say that I am using WebBrowser ActiveX from Shell.Explorer which is ready to use without any registration or something similar. First, here is how you should create textbox:
Code: Select all
Set edtFilter = SDB.UI.NewActiveX(Form, "Shell.Explorer")
edtFilter.Common.SetRect 66, 209, 454, 50
edtFilter.Common.Anchors = 1 + 2 + 4 + 8
sTmp = "<html><head><style type='text/css'>" _
& "body {margin: 0px 0px; overflow: hidden; border: none} " _
& "textarea {font: 12px 'courier new' 'serif'; overflow: auto;" _
& " margin: 0px 0px;"
If bSkinned Then
sTmp = sTmp & " border: 1px solid;"
Else
sTmp = sTmp & ""
End If
sTmp = sTmp & " width: 454px; height: 49px}</style></head>"
sTmp = sTmp & "<script type='text/javascript'>var iKeyCode</script>" _
& "<body" _
& " onkeydown = 'iKeyCode = event.keyCode;'" _
& " onkeyup = 'iKeyCode = """";'" _
& " onfocusout = 'if(iKeyCode == 38 || iKeyCode == 40)" _
& " event.srcElement.focus();'"
' Previous statement is needed because of MM bug with the up/down keys
' which transfer focus to the other controls on the form when the textual
' cursor is on the top/bottom of this control.
sTmp = sTmp & " onresize = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight - 1'"
' Previous statement is needed for textarea element to have same size
' as its parent.
sTmp = sTmp & " onload = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight - 1'"
' Strange, onload = 'this.fireEvent(""onresize"");' doesn't work.
sTmp = sTmp & " oncontextmenu = 'if(this.firstChild.disabled)return false;'"
' Pervious line is needed because the context menu is displayed by
' the right-click even when a control is disabled.
sTmp = sTmp & "><textarea></textarea></body></html>"
edtFilter.SetHTMLDocument sTmp
Script.RegisterEvent edtFilter.Interf.document.body.firstChild, _
"onpropertychange", "edtFilter_OnChange"
Script.RegisterEvent edtFilter.Interf.document, "onselectionchange", _
"edtFilter_OnSelect"
Many properties of this control like border and font could be set with the style element of the WebBrowser control as you could see from the previous code. Next, we could respond on events and then we have two functions to get/set textual value of this control:
Code: Select all
Sub edtFilter_OnSelect()
' ...
End Sub
Sub edtFilter_OnChange()
' ...
End Sub
Sub SetEditBoxText(oCtrl, sText)
If Not oCtrl.Interf.document.getElementsByTagName("textarea").Item(0) _
Is Nothing Then
oCtrl.Interf.document _
.getElementsByTagName("textarea").Item(0).innerText = sText
End If
End Sub
Function GetEditBoxText(oCtrl)
If Not oCtrl.Interf.document.getElementsByTagName("textarea").Item(0) _
Is Nothing Then
GetEditBoxText = oCtrl.Interf.document _
.getElementsByTagName("textarea").Item(0).innerText
End If
End Function
When you want to get text from control you should write GetEditBoxText(edtFilter) where edtFilter is a name of this control, and when you want to set text to control you should write SetEditBoxText edtFilter, "some text string". There is only one more thing which should be mentioned about this control - its Enabled state. I didn't create new procedure for this, instead I used just one line:
edtFilter.Interf.document.body.firstChild.disabled = ... Well, you could try with edtFilter.Common.Enabled = ... but you would get some strange results. I could also explain how I get/set selected part of text, but you should take a look on the Magic Nodes script to find this.
Now, about listbox control... First, here is how we could create it:
Code: Select all
Set lstNodes = SDB.UI.NewActiveX(Form, "Shell.Explorer")
lstNodes.Common.SetRect 254, 75, 155, 97
lstNodes.Common.Anchors = 1 + 2 + 4
sTmp = "<html><head><style type='text/css'>" _
& "body {margin: 0px 0px; overflow: hidden; border: none} " _
& "select {font: 11px 'tahoma' 'sans-serif'; margin: 0px 0px;" _
& "</style></head><body"
sTmp = sTmp & " onresize = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight'"
' Previous statement is needed for select element to have same size
' as its parent.
sTmp = sTmp & " onload = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight'"
' Strange, onload = 'this.fireEvent(""onresize"");' doesn't work.
sTmp = sTmp & "><select size = '100'" ' Setting for listboxes
sTmp = sTmp & " onmousedown = 'this.focus()'" ' Because of skinned MM bug
sTmp = sTmp & "></select></body></html>"
lstNodes.SetHTMLDocument sTmp
Script.RegisterEvent lstNodes.Interf.document.body.firstChild, _
"onchange", "lstNodes_OnChange"
Then we have event handler and several functions to get/set the selected row in this listbox and its text value, as well as to get the number of rows and to add/insert/remove some row:
Code: Select all
Sub lstNodes_OnChange()
' ...
End Sub
Sub ListBoxAddItem(oCtrl, sText)
Dim oSelect, oOption, bDisabled
Set oSelect = oCtrl.Interf.document.getElementsByTagName("select").Item(0)
Set oOption = oCtrl.Interf.document.createElement("option")
If Not oSelect.disabled Then
oSelect.disabled = True
' Really stupid thing! This workaround with temporary disabling
' the select element is because adding the option to this element
' takes the focus from the another active control!!!
Else
bDisabled = True
End If
oSelect.add oOption
If Not bDisabled Then oSelect.disabled = False
oOption.text = sText
End Sub
Sub ListBoxInsertItem(oCtrl, sText, iIndex)
Dim oSelect, oOption, bDisabled
Set oSelect = oCtrl.Interf.document.getElementsByTagName("select").Item(0)
If iIndex < oSelect.length Then
Set oOption = oCtrl.Interf.document.createElement("option")
If Not oSelect.disabled Then
oSelect.disabled = True
Else
bDisabled = True
End If
oSelect.options.add oOption, iIndex + 1
If Not bDisabled Then oSelect.disabled = False
oOption.text = sText
End If
End Sub
Sub ListBoxRemoveItem(oCtrl, iIndex)
oCtrl.Interf.document.getElementsByTagName("select").Item(0).remove iIndex
End Sub
Function ListBoxListCount(oCtrl)
ListBoxListCount = oCtrl.Interf.document.getElementsByTagName("select") _
.Item(0).length
End Function
Sub SetListBoxListIndex(oCtrl, iIndex)
oCtrl.Interf.document.getElementsByTagName("select") _
.Item(0).selectedIndex = iIndex
End Sub
Function GetListBoxListIndex(oCtrl)
GetListBoxListIndex = oCtrl.Interf.document.getElementsByTagName("select") _
.Item(0).selectedIndex
End Function
Sub SetListBoxListText(oCtrl, iIndex, sText)
Dim oSelect
Set oSelect = oCtrl.Interf.document.getElementsByTagName("select").Item(0)
If Not oSelect Is Nothing And iIndex >= 0 Then
If iIndex < oSelect.length Then
oSelect.options(iIndex).text = sText
End If
End If
End Sub
Function GetListBoxListText(oCtrl, iIndex)
Dim oSelect
Set oSelect = oCtrl.Interf.document.getElementsByTagName("select").Item(0)
If Not oSelect Is Nothing And iIndex >= 0 Then
If iIndex < oSelect.length Then
GetListBoxListText = oSelect.options(iIndex).text
End If
End If
End Function
Similar as with textbox control, you should use following line to enable/disable listbox control: lstNodes.Interf.document.body.firstChild.disabled = ... Unfortunately, with the listbox it is not easy task to change its border. You could try to set its margins to some negative value (e.g. -2px) to hide default border or something similar, but I left it like it is.
On the end of this post I am presenting one complete function (in fact two) which could be used as a multi-line replacement for a single-lined SkinnedInputBox window which could be seen in some MM scripts:
Code: Select all
' Some necessary global variables:
Dim sInputText
Dim edtInput
Function MultilineInputBox(sLabel, sCaption, sEditText)
Dim oForm
Dim lblCtrl
Dim btnOK
Dim btnCancel
Dim iBorderWidth
Dim iBorderHeight
Dim sTmp
Set oForm = SDB.UI.NewForm
oForm.BorderStyle = 2 ' Resizable
iBorderWidth = oForm.Common.Width - oForm.Common.ClientWidth
iBorderHeight = oForm.Common.Height - oForm.Common.ClientHeight
oForm.Common.SetRect 100, 100, 515 + iBorderWidth, 445 + iBorderHeight
oForm.Common.MinWidth = 365 + iBorderWidth
oForm.Common.MinHeight = 95 + + iBorderHeight
oForm.FormPosition = 4 ' Screen Center
oForm.Caption = sCaption
Set lblCtrl = SDB.UI.NewLabel(oForm)
lblCtrl.Caption = sLabel
lblCtrl.Common.Left = 10
lblCtrl.Common.Top = 10
Set edtInput = SDB.UI.NewActiveX(oForm, "Shell.Explorer")
edtInput.Common.SetRect 10, 30, 493, 375
edtInput.Common.Anchors = 1 + 2 + 4 + 8
sTmp = "<html"
sTmp = sTmp & "><head><style type='text/css'>" _
& "body {margin: 0px 0px; overflow: hidden; border: none} " _
& "textarea {font: 12px 'courier new' 'serif'; overflow: auto;" _
& " margin: 0px 0px;}</style></head>"
sTmp = sTmp & "<script type='text/javascript'>var iKeyCode</script>" _
& "<body" _
& " onkeydown = 'iKeyCode = event.keyCode;'" _
& " onkeyup = 'iKeyCode = """";'" _
& " onfocusout = 'if(iKeyCode == 38 || iKeyCode == 40)" _
& " event.srcElement.focus();'"
' Previous statement is needed because of MM bug with the up/down keys
' which transfer focus to the other controls on the form when the textual
' cursor is on the top/bottom of this control.
sTmp = sTmp & " onresize = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight - 1'"
' Previous statement is needed for textarea element to have same size
' as its parent.
sTmp = sTmp & " onload = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight - 1'"
' Previous statement is needed because of non-skinned version which doesn't
' raise the onresize event when opening dialog.
' Strange, onload = 'this.fireEvent(""onresize"");' doesn't work.
sTmp = sTmp & "><textarea>" & sEditText & "</textarea></body></html>"
edtInput.SetHTMLDocument sTmp
Script.RegisterEvent edtInput.Interf.document.body.firstChild, _
"onpropertychange", "edtInput_OnChange"
Set SDB.Objects("MNedtInput") = edtInput
sInputText = sEditText
Set btnOK = SDB.UI.NewButton(oForm)
btnOK.Caption = "&OK"
btnOK.Common.SetRect 350, 413, 73, 24
btnOK.Common.Anchors = 4 + 8
btnOK.UseScript = Script.ScriptPath
btnOK.Default = True
btnOK.Common.Enabled = False
btnOK.ModalResult = 1
Set SDB.Objects("btnOKInput") = btnOK
Set btnCancel = SDB.UI.NewButton(oForm)
btnCancel.Caption = "&Cancel"
btnCancel.Common.SetRect 430, 413, 73, 24
btnCancel.Common.Anchors = 4 + 8
btnCancel.UseScript = Script.ScriptPath
btnCancel.Cancel = True
btnCancel.modalResult = 2
oForm.SavePositionName = "Multiline InputBox"
If oForm.showModal = 1 Then
MultilineInputBox = sInputText
Else
MultilineInputBox = sEditText
End If
Set SDB.Objects("btnOKInput") = Nothing
End Function
Sub edtInput_OnChange()
sInputText = GetEditBoxText(edtInput)
End Sub
If you find this code examples useful and want to include them in your source code, please be kind and mention my name. I spent significant part of time to discover all of this which is presented here.
As some would like to say - this post is not for users but for scripters. There is not some new script, but explanation and sample code how to get listboxes and multi-line edit controls within your scripts. As you could see with the new (2.0) version of the Magic Nodes script, they are possible to get even with MM2 which don't have built-in multi-line edit control. However, my multi-line edit control is even better then MM3 built-in multi-line edit control! (I'll tell you why somewhat latter). I am sorry if there already exists some script which has something similar like my suggestion, but in that case its author also should be sorry why s/he didn't share his experience with us when we asked for such thing (there are several requests for listbox control in the Scripting Functionality Wishlist thread without any answer).
Some of us have been using some kind of workaround with Forms ActiveX which contain Listbox and Textbox (which have Multiline property), but this solution is not very well for several reasons. First of all, Forms ActiveX should be downloaded from Microsoft site if you don't have installed MS Office, then you should register it. Those controls from this ActiveX have plain old look from Win 95 days, even if you have XP or Vista. This is mostly notable on their borders and scroll bars.
Some of controls from Forms ActiveX have some drawbacks in combination with MediaMonkey, but I think that MM is guilty for this, not control itself. For example, you cannot navigate within listbox control with up and down arrow keys, because MM transfer focus to the next control like when you press Tab or Shift+Tab. I noticed strange behavior with the Textbox control when the cursor is changing between the default (pointer) shape and I-beam shape as you move the mouse over the text, but more ugly thing with the Textbox is its font setting which has an effect only on every second character (i.e. one character has specified font and the next character has default font). Fortunately, my controls don't have such issues.
Well, speaking of fonts, I come to the point when I should tell you why I think that my suggestion is even better than MM3 built-in multi-line edit control (without a fact that my suggestion works with MM2). You could guess - MM3 control don't have Font property. Well, this is not unexpected since none of MM built-in control don't have Font property. Their controls don't have Border property. Their controls don't have Background Color nor Foreground Color properties. Their multi-line edit control don't expose OnSelect event. Their multi-line edit control don't have SelectStart and SelectEnd properties. Well, neither their Edit control don't have those properties. MM developers think that we don't need to know which part of text is selected and where exactly is textual cursor, i.e. after which character. Somebody of them also should tell me why they are created a new control with a new name (Multilineedit). I would expect to get a new boolean property (Multiline) with the existing Edit control, like we have with Visual Basic and Forms Textbox controls, but not totally new control.
And now, most senseless thing about MM3 Multiline edit control - it has not scroll bars at all! Nor horizontal, nor vertical! Just type as much text as you want, but you could not get any scroll bar, neither with the new MM 3.1! Oh well. Even Visual Basic for DOS had text boxes with scroll bars. You know, with my control I could decide when and which scroll bars I want to get (overflow style).
OK, enough talk. If you don't want to go through 420 KB of source code of Magic Nodes script, here are those controls. If you are still wondering how they work, just to say that I am using WebBrowser ActiveX from Shell.Explorer which is ready to use without any registration or something similar. First, here is how you should create textbox:
[code] Set edtFilter = SDB.UI.NewActiveX(Form, "Shell.Explorer")
edtFilter.Common.SetRect 66, 209, 454, 50
edtFilter.Common.Anchors = 1 + 2 + 4 + 8
sTmp = "<html><head><style type='text/css'>" _
& "body {margin: 0px 0px; overflow: hidden; border: none} " _
& "textarea {font: 12px 'courier new' 'serif'; overflow: auto;" _
& " margin: 0px 0px;"
If bSkinned Then
sTmp = sTmp & " border: 1px solid;"
Else
sTmp = sTmp & ""
End If
sTmp = sTmp & " width: 454px; height: 49px}</style></head>"
sTmp = sTmp & "<script type='text/javascript'>var iKeyCode</script>" _
& "<body" _
& " onkeydown = 'iKeyCode = event.keyCode;'" _
& " onkeyup = 'iKeyCode = """";'" _
& " onfocusout = 'if(iKeyCode == 38 || iKeyCode == 40)" _
& " event.srcElement.focus();'"
' Previous statement is needed because of MM bug with the up/down keys
' which transfer focus to the other controls on the form when the textual
' cursor is on the top/bottom of this control.
sTmp = sTmp & " onresize = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight - 1'"
' Previous statement is needed for textarea element to have same size
' as its parent.
sTmp = sTmp & " onload = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight - 1'"
' Strange, onload = 'this.fireEvent(""onresize"");' doesn't work.
sTmp = sTmp & " oncontextmenu = 'if(this.firstChild.disabled)return false;'"
' Pervious line is needed because the context menu is displayed by
' the right-click even when a control is disabled.
sTmp = sTmp & "><textarea></textarea></body></html>"
edtFilter.SetHTMLDocument sTmp
Script.RegisterEvent edtFilter.Interf.document.body.firstChild, _
"onpropertychange", "edtFilter_OnChange"
Script.RegisterEvent edtFilter.Interf.document, "onselectionchange", _
"edtFilter_OnSelect"[/code]
Many properties of this control like border and font could be set with the style element of the WebBrowser control as you could see from the previous code. Next, we could respond on events and then we have two functions to get/set textual value of this control:
[code]Sub edtFilter_OnSelect()
' ...
End Sub
Sub edtFilter_OnChange()
' ...
End Sub
Sub SetEditBoxText(oCtrl, sText)
If Not oCtrl.Interf.document.getElementsByTagName("textarea").Item(0) _
Is Nothing Then
oCtrl.Interf.document _
.getElementsByTagName("textarea").Item(0).innerText = sText
End If
End Sub
Function GetEditBoxText(oCtrl)
If Not oCtrl.Interf.document.getElementsByTagName("textarea").Item(0) _
Is Nothing Then
GetEditBoxText = oCtrl.Interf.document _
.getElementsByTagName("textarea").Item(0).innerText
End If
End Function[/code]
When you want to get text from control you should write GetEditBoxText(edtFilter) where edtFilter is a name of this control, and when you want to set text to control you should write SetEditBoxText edtFilter, "some text string". There is only one more thing which should be mentioned about this control - its Enabled state. I didn't create new procedure for this, instead I used just one line:
edtFilter.Interf.document.body.firstChild.disabled = ... Well, you could try with edtFilter.Common.Enabled = ... but you would get some strange results. I could also explain how I get/set selected part of text, but you should take a look on the Magic Nodes script to find this.
Now, about listbox control... First, here is how we could create it:
[code] Set lstNodes = SDB.UI.NewActiveX(Form, "Shell.Explorer")
lstNodes.Common.SetRect 254, 75, 155, 97
lstNodes.Common.Anchors = 1 + 2 + 4
sTmp = "<html><head><style type='text/css'>" _
& "body {margin: 0px 0px; overflow: hidden; border: none} " _
& "select {font: 11px 'tahoma' 'sans-serif'; margin: 0px 0px;" _
& "</style></head><body"
sTmp = sTmp & " onresize = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight'"
' Previous statement is needed for select element to have same size
' as its parent.
sTmp = sTmp & " onload = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight'"
' Strange, onload = 'this.fireEvent(""onresize"");' doesn't work.
sTmp = sTmp & "><select size = '100'" ' Setting for listboxes
sTmp = sTmp & " onmousedown = 'this.focus()'" ' Because of skinned MM bug
sTmp = sTmp & "></select></body></html>"
lstNodes.SetHTMLDocument sTmp
Script.RegisterEvent lstNodes.Interf.document.body.firstChild, _
"onchange", "lstNodes_OnChange"
[/code]
Then we have event handler and several functions to get/set the selected row in this listbox and its text value, as well as to get the number of rows and to add/insert/remove some row:
[code]Sub lstNodes_OnChange()
' ...
End Sub
Sub ListBoxAddItem(oCtrl, sText)
Dim oSelect, oOption, bDisabled
Set oSelect = oCtrl.Interf.document.getElementsByTagName("select").Item(0)
Set oOption = oCtrl.Interf.document.createElement("option")
If Not oSelect.disabled Then
oSelect.disabled = True
' Really stupid thing! This workaround with temporary disabling
' the select element is because adding the option to this element
' takes the focus from the another active control!!!
Else
bDisabled = True
End If
oSelect.add oOption
If Not bDisabled Then oSelect.disabled = False
oOption.text = sText
End Sub
Sub ListBoxInsertItem(oCtrl, sText, iIndex)
Dim oSelect, oOption, bDisabled
Set oSelect = oCtrl.Interf.document.getElementsByTagName("select").Item(0)
If iIndex < oSelect.length Then
Set oOption = oCtrl.Interf.document.createElement("option")
If Not oSelect.disabled Then
oSelect.disabled = True
Else
bDisabled = True
End If
oSelect.options.add oOption, iIndex + 1
If Not bDisabled Then oSelect.disabled = False
oOption.text = sText
End If
End Sub
Sub ListBoxRemoveItem(oCtrl, iIndex)
oCtrl.Interf.document.getElementsByTagName("select").Item(0).remove iIndex
End Sub
Function ListBoxListCount(oCtrl)
ListBoxListCount = oCtrl.Interf.document.getElementsByTagName("select") _
.Item(0).length
End Function
Sub SetListBoxListIndex(oCtrl, iIndex)
oCtrl.Interf.document.getElementsByTagName("select") _
.Item(0).selectedIndex = iIndex
End Sub
Function GetListBoxListIndex(oCtrl)
GetListBoxListIndex = oCtrl.Interf.document.getElementsByTagName("select") _
.Item(0).selectedIndex
End Function
Sub SetListBoxListText(oCtrl, iIndex, sText)
Dim oSelect
Set oSelect = oCtrl.Interf.document.getElementsByTagName("select").Item(0)
If Not oSelect Is Nothing And iIndex >= 0 Then
If iIndex < oSelect.length Then
oSelect.options(iIndex).text = sText
End If
End If
End Sub
Function GetListBoxListText(oCtrl, iIndex)
Dim oSelect
Set oSelect = oCtrl.Interf.document.getElementsByTagName("select").Item(0)
If Not oSelect Is Nothing And iIndex >= 0 Then
If iIndex < oSelect.length Then
GetListBoxListText = oSelect.options(iIndex).text
End If
End If
End Function
[/code]
Similar as with textbox control, you should use following line to enable/disable listbox control: lstNodes.Interf.document.body.firstChild.disabled = ... Unfortunately, with the listbox it is not easy task to change its border. You could try to set its margins to some negative value (e.g. -2px) to hide default border or something similar, but I left it like it is.
On the end of this post I am presenting one complete function (in fact two) which could be used as a multi-line replacement for a single-lined SkinnedInputBox window which could be seen in some MM scripts:
[code]' Some necessary global variables:
Dim sInputText
Dim edtInput
Function MultilineInputBox(sLabel, sCaption, sEditText)
Dim oForm
Dim lblCtrl
Dim btnOK
Dim btnCancel
Dim iBorderWidth
Dim iBorderHeight
Dim sTmp
Set oForm = SDB.UI.NewForm
oForm.BorderStyle = 2 ' Resizable
iBorderWidth = oForm.Common.Width - oForm.Common.ClientWidth
iBorderHeight = oForm.Common.Height - oForm.Common.ClientHeight
oForm.Common.SetRect 100, 100, 515 + iBorderWidth, 445 + iBorderHeight
oForm.Common.MinWidth = 365 + iBorderWidth
oForm.Common.MinHeight = 95 + + iBorderHeight
oForm.FormPosition = 4 ' Screen Center
oForm.Caption = sCaption
Set lblCtrl = SDB.UI.NewLabel(oForm)
lblCtrl.Caption = sLabel
lblCtrl.Common.Left = 10
lblCtrl.Common.Top = 10
Set edtInput = SDB.UI.NewActiveX(oForm, "Shell.Explorer")
edtInput.Common.SetRect 10, 30, 493, 375
edtInput.Common.Anchors = 1 + 2 + 4 + 8
sTmp = "<html"
sTmp = sTmp & "><head><style type='text/css'>" _
& "body {margin: 0px 0px; overflow: hidden; border: none} " _
& "textarea {font: 12px 'courier new' 'serif'; overflow: auto;" _
& " margin: 0px 0px;}</style></head>"
sTmp = sTmp & "<script type='text/javascript'>var iKeyCode</script>" _
& "<body" _
& " onkeydown = 'iKeyCode = event.keyCode;'" _
& " onkeyup = 'iKeyCode = """";'" _
& " onfocusout = 'if(iKeyCode == 38 || iKeyCode == 40)" _
& " event.srcElement.focus();'"
' Previous statement is needed because of MM bug with the up/down keys
' which transfer focus to the other controls on the form when the textual
' cursor is on the top/bottom of this control.
sTmp = sTmp & " onresize = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight - 1'"
' Previous statement is needed for textarea element to have same size
' as its parent.
sTmp = sTmp & " onload = '" _
& "document.body.firstChild.style.posWidth " _
& "= document.body.offsetWidth; " _
& "document.body.firstChild.style.posHeight " _
& "= document.body.offsetHeight - 1'"
' Previous statement is needed because of non-skinned version which doesn't
' raise the onresize event when opening dialog.
' Strange, onload = 'this.fireEvent(""onresize"");' doesn't work.
sTmp = sTmp & "><textarea>" & sEditText & "</textarea></body></html>"
edtInput.SetHTMLDocument sTmp
Script.RegisterEvent edtInput.Interf.document.body.firstChild, _
"onpropertychange", "edtInput_OnChange"
Set SDB.Objects("MNedtInput") = edtInput
sInputText = sEditText
Set btnOK = SDB.UI.NewButton(oForm)
btnOK.Caption = "&OK"
btnOK.Common.SetRect 350, 413, 73, 24
btnOK.Common.Anchors = 4 + 8
btnOK.UseScript = Script.ScriptPath
btnOK.Default = True
btnOK.Common.Enabled = False
btnOK.ModalResult = 1
Set SDB.Objects("btnOKInput") = btnOK
Set btnCancel = SDB.UI.NewButton(oForm)
btnCancel.Caption = "&Cancel"
btnCancel.Common.SetRect 430, 413, 73, 24
btnCancel.Common.Anchors = 4 + 8
btnCancel.UseScript = Script.ScriptPath
btnCancel.Cancel = True
btnCancel.modalResult = 2
oForm.SavePositionName = "Multiline InputBox"
If oForm.showModal = 1 Then
MultilineInputBox = sInputText
Else
MultilineInputBox = sEditText
End If
Set SDB.Objects("btnOKInput") = Nothing
End Function
Sub edtInput_OnChange()
sInputText = GetEditBoxText(edtInput)
End Sub
[/code]
If you find this code examples useful and want to include them in your source code, please be kind and mention my name. I spent significant part of time to discover all of this which is presented here.