Unicode対応リストボックスの作成

解決


まさ  2005-11-04 21:47:07  No: 127314

前回、Unicode文字の入力、表示について質問させていただきました。

VBの標準コントロールには、Unicode文字の入力、表示が不可能とのことでしたので、
現在、魔界の仮面弁士さんが作成したサンプル(↓)を元に
http://www.ocv.ne.jp/~oratorio/windev/vb/UnicodeTextBox.lzh
Unicode文字の入力、表示に対応した複数のコントロール(テキストボックス、コマンドボタン、
ラベル)を作成しております。

標準コントロールのコンボボックスやリストボックスの機能を、同様に作成したいのですが、
Listプロパティをどのように作成したらいいのか頭を悩ませています。

WebBrowserでこの機能を作成する以外に方法がありますでしょうか?
ご教授お願い致します。


魔界の仮面弁士  2005-11-04 22:10:27  No: 127315

> 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 を利用して
設定させる形式をとればよいのではないかと。


まさ  2005-11-05 03:14:17  No: 127316

>> 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


魔界の仮面弁士  2005-11-05 05:14:43  No: 127317

> 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 を返す。
のどちらかの状態になっているのだと思います。確認してみてください。


まさ  2005-11-07 21:57:15  No: 127318

>で、もしも  List = ComboControl.Options(Index) のような記述なのに、
>『オブジェクト変数または〜』の実行時エラーが出るだとしたら、
>  1) ComboControl が Nothing の状態である。
>  2) ComboControl.Options(Index) が Nothing を返す。
>のどちらかの状態になっているのだと思います。確認してみてください。

ComboControlは「HTMLSelectElement」オブジェクトとして認識されています。
が、Optionsプロパティが配列になっていないようです。
「2)の ComboControl.Options(Index) が Nothing を返す。」ということになりますかね?

ComboControlの「type」プロパティが「select-one」になっているのが関係しているのでしょうか?


魔界の仮面弁士  2005-11-07 22:07:29  No: 127319

> 「2)の ComboControl.Options(Index) が Nothing を返す。」ということになりますかね?

とすると、
  2.1 ComboControl.Options が Nothing を返す。
  2.2 ComboControl.Options(index) が Nothing を返す。
のいずれかですね。

もしも後者だとしたら、
  indexのデータ型は何か。(VariantとかStringとかIntegerとかLongとか)
  indexの範囲は適切か。(項目数を超える範囲を操作していないか)
を確認してみてください。

それに付随して、Property Let側の処理に問題が無いかも確認を。


まさ  2005-11-07 23:53:57  No: 127320

>  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) = "あいうえお"


魔界の仮面弁士  2005-11-08 01:16:50  No: 127321

> そもそも、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 するための処理も必要ですし。


まさ  2005-11-09 01:41:57  No: 127322

魔界の仮面弁士様、いつも的確な回答ありがとうございます。
アドバイスを元に、いろいろ試してみたのですが・・・・全く進みません。。。
私の理解力が不足していることもかなり大きいのですが、下記内容について私の認識違いを
ご指摘願えませんか?

  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 するための処理も必要ですし。
具体的にはどのように記述しなければならないのでしょうか?


魔界の仮面弁士  2005-11-09 11:13:12  No: 127323

>     ComboControl.Options(Index).Value = vNewValue
この時、ComboControl に登録されている項目(OPTION)の数は幾つですか?
そして、Indexの値は幾つですか?

Indexの数が負数だったり、項目数を超えていたりした場合は、
それに対応するコードが必要になりますよね。

> ComboControl.Options.selectedIndex = Index
> ComboControl.Options.Value = vNewValue
先に提示した URL の内容を、もう一度よく見てください。
optionsコレクションに、selectedIndex や Value などいう
プロパティはありませんよ。
(selectオブジェクトとoptionsコレクションを混同していませんか?)


魔界の仮面弁士  2005-11-09 11:15:56  No: 127324

>>項目を追加する場合は、新たな option要素を add するための処理も必要ですし。
> 具体的にはどのように記述しなければならないのでしょうか?

? そのまま、文字通りの処理ですよ。
新たな option要素を作成して、add してください。

「add メソッド (optionsコレクション)」
http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/add.asp


まさ  2005-11-11 01:41:54  No: 127325

>(selectオブジェクトとoptionsコレクションを混同していませんか?)
はい。その通りです。

私はてっきり「selectオブジェクトに属するoptionsコレクション」のような考え方をしていました。
ですからoptionsコレクションをcreateしていなかったのです。

魔界の仮面弁士さんにアドバイスいただいて、ようやく理解できた感じです。
ありがとうございました。


まさ  2005-11-11 01:48:32  No: 127326

チェックし忘れました


まさ  2005-11-11 01:54:58  No: 127327

>ですからoptionsコレクションをcreateしていなかったのです。
すみません。なんかおかしな表現をしてしまいました。

「option要素をcreateしておらず、optionsコレクションもaddしていなかった」
ということを言いたかったのです。


魔界の仮面弁士  2005-11-11 02:10:32  No: 127328

> ですから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


魔界の仮面弁士  2005-11-11 02:18:11  No: 127329

うっ。投稿している最中に、すれ違ってしまったようですね……。(^^;
何はともあれ、解決できたようで何よりです。

なお、上記のコードは掲示板上で直に書いたものなので、
動作チェックはしていません。間違っていたら済みません。m(_ _)m


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加