前回、Unicode文字の入力、表示について質問させていただきました。
VBの標準コントロールには、Unicode文字の入力、表示が不可能とのことでしたので、
現在、魔界の仮面弁士さんが作成したサンプル(↓)を元に
http://www.ocv.ne.jp/~oratorio/windev/vb/UnicodeTextBox.lzh
Unicode文字の入力、表示に対応した複数のコントロール(テキストボックス、コマンドボタン、
ラベル)を作成しております。
標準コントロールのコンボボックスやリストボックスの機能を、同様に作成したいのですが、
Listプロパティをどのように作成したらいいのか頭を悩ませています。
WebBrowserでこの機能を作成する以外に方法がありますでしょうか?
ご教授お願い致します。
> WebBrowserでこの機能を作成する以外に方法がありますでしょうか?
手っ取り早いのは、Unicode対応ListBoxを使う事…かな。(^^;
http://www.cyberactivex.com/product008.htm
# あまりお奨めはしませんが、FM20.DLL を使うという最後の手段も。
> Listプロパティをどのように作成したらいいのか頭を悩ませています。
VB6版の実装を真似るならば、Listプロパティの定義は
Public Property Get List(ByVal Index As Integer) As String
で良いのではないでしょうか。
# 別案として、
# Public Property Get List() As String()
# Public Property Get List() As VBA.Collection
# Public Property Get List() As Scripting.Dictionary
# などという実装方法も考えられますが…。
で。実行時ではなく、デザイン時のListプロパティの動作の事だとしたら、
VB6版ListBoxの動作を真似るのは難しそうなので、諦めて実行時専用の
プロパティとして実装してしまった方が無難かも知れません。
もし、デザイン時にも設定したいなら、PropertyPage を利用して
設定させる形式をとればよいのではないかと。
>> WebBrowserでこの機能を作成する以外に方法がありますでしょうか?
>手っ取り早いのは、Unicode対応ListBoxを使う事…かな。(^^;
>http://www.cyberactivex.com/product008.htm
># あまりお奨めはしませんが、FM20.DLL を使うという最後の手段も。
それが、上記のUnicode対応ListBoxも、FM20.DLLも、今回のツールで使用するオリジナルフォントの
外字領域に設定した文字が表示されないのでWebBrowserでの実装に踏み切った次第です。
>> Listプロパティをどのように作成したらいいのか頭を悩ませています。
>VB6版の実装を真似るならば、Listプロパティの定義は
> Public Property Get List(ByVal Index As Integer) As String
>で良いのではないでしょうか。
プロパティの動作は実行時でかまいません。
ですが、値の取得だけではなく設定もしたいのです。
Property Getステートメントは値の取得になりますよね?
そして、このステートメントのコードなのですが、たとえば魔界の仮面弁士さんが作成された
サンプルロジックで、テキストボックスのコントロールを作成した場合、
Public Property Get Text() As String
Text = TextControl.Value
End Property
このように、コントロールのValueプロパティをTextプロパティに設定しますよね?
これをふまえて、Listプロパティを設定しようとした場合、何を参照すれば良いのかが分かりませんでした。
CreatElementで「Select」のエレメントを作成した場合、「Options」プロパティなどにインデックス指定で
設定させればいいのかと思い、下記のコードを実行しましたが、
「オブジェクト変数またはWithブロック変数が設定されていません」のエラーになってしまいます。
Public Property Get List(ByVal Index As Integer) As String
List(Index) = ComboControl.Options(Index)
End Property
> Property Getステートメントは値の取得になりますよね?
ですます。必要に応じて、Property Let / Set の方も作成してください。
> 「Options」プロパティなどにインデックス指定で
> 設定させればいいのかと思い、
考え方は、それで合ってますよ。
> Public Property Get List(ByVal Index As Integer) As String
> List(Index) = ComboControl.Options(Index)
> End Property
これですと、List プロパティへ Let している事になってしまいますよ。
Property Get への戻り値として返したいのであれば、
List = ComboControl.Options(Index)
のように書きます。
で、もしも List = ComboControl.Options(Index) のような記述なのに、
『オブジェクト変数または〜』の実行時エラーが出るだとしたら、
1) ComboControl が Nothing の状態である。
2) ComboControl.Options(Index) が Nothing を返す。
のどちらかの状態になっているのだと思います。確認してみてください。
>で、もしも List = ComboControl.Options(Index) のような記述なのに、
>『オブジェクト変数または〜』の実行時エラーが出るだとしたら、
> 1) ComboControl が Nothing の状態である。
> 2) ComboControl.Options(Index) が Nothing を返す。
>のどちらかの状態になっているのだと思います。確認してみてください。
ComboControlは「HTMLSelectElement」オブジェクトとして認識されています。
が、Optionsプロパティが配列になっていないようです。
「2)の ComboControl.Options(Index) が Nothing を返す。」ということになりますかね?
ComboControlの「type」プロパティが「select-one」になっているのが関係しているのでしょうか?
> 「2)の ComboControl.Options(Index) が Nothing を返す。」ということになりますかね?
とすると、
2.1 ComboControl.Options が Nothing を返す。
2.2 ComboControl.Options(index) が Nothing を返す。
のいずれかですね。
もしも後者だとしたら、
indexのデータ型は何か。(VariantとかStringとかIntegerとかLongとか)
indexの範囲は適切か。(項目数を超える範囲を操作していないか)
を確認してみてください。
それに付随して、Property Let側の処理に問題が無いかも確認を。
> 2.2 ComboControl.Options(index) が Nothing を返す。
こちらでした。
>もしも後者だとしたら、
> indexのデータ型は何か。(VariantとかStringとかIntegerとかLongとか)
データ型はIntegerにしています。
> indexの範囲は適切か。(項目数を超える範囲を操作していないか)
>を確認してみてください。
そもそも、Optionsプロパティは配列になっていないのではないかと・・・。
(ウォッチウインドウで確認したのですが)
明示的に指定しなければならなかったりするのでしょうか?
>それに付随して、Property Let側の処理に問題が無いかも確認を。
下記処理では「実装されていません」のエラーが発生します。
Public Property Let List(ByVal Index As Integer, ByVal vNewValue As String)
ComboControl.Options(Index) = vNewValue
UserControl.PropertyChanged "List"
End Property
呼び出し元の処理はこんな感じです。↓
UnicodeComboBox1.List(0) = "あいうえお"
> そもそも、Optionsプロパティは配列になっていないのではないかと・・・。
optionsプロパティは、配列ではありません。
それ自体が options というコレクションです。
「optionsコレクション」
http://msdn.microsoft.com/workshop/author/dhtml/reference/collections/options.asp
> ComboControl.Options(Index) = vNewValue
options(i) は、option要素を返します。Stringを代入しては駄目ですよ。
option要素には、value、text、selected、runtimeStyleなどといった
幾つかのプロパティがあります。SDKで確認してみてください。
「optionオブジェクト」
http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/option.asp
それと、いきなり index を使うのではなく、index 値の範囲を
チェックしてから使った方が良いでしょう。
項目を追加する場合は、新たな option要素を add するための処理も必要ですし。
魔界の仮面弁士様、いつも的確な回答ありがとうございます。
アドバイスを元に、いろいろ試してみたのですが・・・・全く進みません。。。
私の理解力が不足していることもかなり大きいのですが、下記内容について私の認識違いを
ご指摘願えませんか?
Public Property Let List(ByVal Index As Integer, ByVal vNewValue As String)
ComboControl.Options(Index).Value = vNewValue
UserControl.PropertyChanged "List"
End Property
option要素のvalueプロパティに値を代入するイメージで上記コードを実行していましたが、
「ComboControl.Options(index)」が相変わらずNothingを返すため『オブジェクト変数または〜』の
エラーがでてしまいます。
そして、Optionsコレクションの「selectedIndes」と「Value」プロパティに値を代入しようと
したのですが、実行はされるもののセットされません。
Public Property Let List(ByVal Index As Integer, ByVal vNewValue As String)
ComboControl.Options.selectedIndex = Index
ComboControl.Options.Value = vNewValue
UserControl.PropertyChanged "List"
End Property
>項目を追加する場合は、新たな option要素を add するための処理も必要ですし。
具体的にはどのように記述しなければならないのでしょうか?
> ComboControl.Options(Index).Value = vNewValue
この時、ComboControl に登録されている項目(OPTION)の数は幾つですか?
そして、Indexの値は幾つですか?
Indexの数が負数だったり、項目数を超えていたりした場合は、
それに対応するコードが必要になりますよね。
> ComboControl.Options.selectedIndex = Index
> ComboControl.Options.Value = vNewValue
先に提示した URL の内容を、もう一度よく見てください。
optionsコレクションに、selectedIndex や Value などいう
プロパティはありませんよ。
(selectオブジェクトとoptionsコレクションを混同していませんか?)
>>項目を追加する場合は、新たな option要素を add するための処理も必要ですし。
> 具体的にはどのように記述しなければならないのでしょうか?
? そのまま、文字通りの処理ですよ。
新たな option要素を作成して、add してください。
「add メソッド (optionsコレクション)」
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/add.asp
>(selectオブジェクトとoptionsコレクションを混同していませんか?)
はい。その通りです。
私はてっきり「selectオブジェクトに属するoptionsコレクション」のような考え方をしていました。
ですからoptionsコレクションをcreateしていなかったのです。
魔界の仮面弁士さんにアドバイスいただいて、ようやく理解できた感じです。
ありがとうございました。
チェックし忘れました
>ですからoptionsコレクションをcreateしていなかったのです。
すみません。なんかおかしな表現をしてしまいました。
「option要素をcreateしておらず、optionsコレクションもaddしていなかった」
ということを言いたかったのです。
> ですからoptionsコレクションをcreateしていなかったのです。
作成するのは、「option」です。
「options」を作成する必要はありませんよ。
(optionsコレクションは、ComboControl.options から取得できます)
処理のイメージとしては、こんな感じになると思います。
-----------
'Property Let 時のプロパティ引数として渡された Index が、
'『0』〜『項目数(<option>要素の数) - 1』の範囲であるかどうか、
'チェックし、範囲外の値の時はエラーにする。
Dim MaxIndex As Integer
MaxIndex = ComboControl.options.length
If Index < 0 Or Index >= MaxIndex Then
Err.Raise 381
End If
'項目の編集
'ComboControl.options(Index).value = vNewValue
ComboControl.options(Index).text = vNewValue
----------
もし、VB6 の ComboBox や ListBox の List プロパティの実装を真似て、
「Index = 項目数」の時に、新たな項目が追加されるようにしたいならば、
createElement メソッドを用いて、新たな OPTION を作成し、それを
options コレクションの add メソッドで追加するようにします。
-----------
Dim Opt As Object
If Index < 0 Or Index > MaxIndex Then
'範囲外エラー
Err.Raise 381
ElseIf Index = MaxIndex Then
'新しい項目を作成し、それを追加する
Set Opt = objDocument.createElement("OPTION")
'コレクションの最後に追加する時には、
'addメソッドの第2引数を省略することができる。
ComboControl.options.add Opt
Else
'既存の項目を取得
Set Opt = ComboControl.options(Index)
End If
'項目の編集
'Opt.value = vNewValue
Opt.text = vNewValue
Set Opt = Nothing
うっ。投稿している最中に、すれ違ってしまったようですね……。(^^;
何はともあれ、解決できたようで何よりです。
なお、上記のコードは掲示板上で直に書いたものなので、
動作チェックはしていません。間違っていたら済みません。m(_ _)m
ツイート | ![]() |