テキストボックスで漢字の入力をさせているのですが、
溱(シン)とか溙(タイ)などの文字をIMEパッドから入力すると
確定後、?に変ってしまうのですが、どこかに設定が有るのでしょうか
VB標準のTextBoxコントロールは、Unicode対応コントロールでは
ありませんので、残念ながら無理です。
Unicode対応という事であれば、WebBrowserコントロールに、
HTMLの<input type=text>や<textarea>などを配置し、
それを利用するという方法があります。
# ちなみに、Microsoft Forms 2.0のTextBoxコントロールでも
# Unicode入力は可能ですが、VBからの利用はあまりお奨めできません。
とりあえず、WebBrowserを使うならばこんな感じです。
Option Explicit
Private Text1 As Object
Private Sub Form_Initialize()
Dim doc As Object
Dim body As Object
'空のページを作成
WebBrowser1.Navigate2 "about:blank"
'初期化完了まで待機
Do While WebBrowser1.Busy
DoEvents
Loop
On Error Resume Next
Do
DoEvents
Set doc = WebBrowser1.Document
Set body = doc.body
Loop While body Is Nothing
On Error GoTo 0
'余白部を消す
With body.Style
.BorderStyle = "none"
.margin = "0px"
.overflow = "hidden"
End With
'単一行のテキストボックスの場合
'Set Text1 = doc.CreateElement("INPUT")
'Text1.Type = "text"
'複数行入力可能なテキストボックスの場合
Set Text1 = doc.CreateElement("TEXTAREA")
'テキストボックスのサイズをWebBrowserの領域いっぱいにする
Text1.runtimeStyle.Width = "100%"
Text1.runtimeStyle.Height = "100%"
Text1.Value = "初期値の文字列として、[" & ChrW(&H6EB1) & "](シン)や[" _
& ChrW(&H6E99) & "](タイ)を表示させておきますね。"
body.appendChild Text1
Set body = Nothing
Set doc = Nothing
End Sub
Private Sub Command1_Click()
Dim S As String
'現在の値の取得
S = Text1.Value
'新しい文字列の設定
Text1.Value = S
End Sub
なお、VBのMsgBox関数やイミディエイト ウィンドウなどは、
Unicode文字の表示に対応していないので、"?"で表示されます。
# コントロールをUserControlにしておくと、再利用が楽かも。
# 手直しすれば、イベント(onchange, ondblclick等)を拾う事もできます。
有難う御座います、魔界の仮面弁士様
ところで、なぜ下記のTextBox使用は、やめた方が良いのでしょう?
WebBrowserを使用するよりも設定等、簡単なようですが
# ちなみに、Microsoft Forms 2.0のTextBoxコントロールでも
# Unicode入力は可能ですが、VBからの利用はあまりお奨めできません。
> ところで、なぜ下記のTextBox使用は、やめた方が良いのでしょう?
以下のような理由によるものです。
============
[理由 1] 再頒布権限がありません。
VB付属の「Redist.txt」には、このコンポーネント(FM20.DLL)に関する記述がありません。
すなわち、VB製EXEと一緒に配布する事はできない事になっているのです。(※1)
(VBAの開発ライセンスを購入すれば、配布できますが)(※2)
なおMicrosoftは、FM20.DLLが VBから利用できるかどうかのテストを行っていませんし、
そもそもVBから利用する事を、一切サポートしないとの事です。(※3)
[理由 2] 幾つかの不具合が報告されています。
・Shift + Tab による前方向移動をサポートしていません。
・まれに、IMEが使えない状態に陥る事があります。
・Office 97以上がインストールされていないと、エラーになる可能性があります。(※4)
・Enterキーで勝手に次のコントロールに移動してしまいます。(これはこれで便利かも?)
------------
(※1) Officeに付属しているコンポーネントなので、実行環境にOfficeが
インストールされていれば、FM20.DLLを配布せずとも動作させることはできます。
Officeが無い場合は、ユーザーに、ActiveX Control Padをインストールしてもらう事に
よって、FM20.DLLを入手してもらうという方法もあります。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaxctrl/html/cpad.asp
(※2) これを、Microsoft Office Developer Edtion(ODE)と混同しないようにしてください。
VBAの開発ライセンスは、ODEとは別物です。
http://www.microsoft.com/japan/msdn/vba/
(※3) http://support.microsoft.com/?kbid=224305
(※4) http://support.microsoft.com/?kbid=241245
有難う御座います、魔界の仮面弁士様
解りました、漢字の入力部分でIMEが使えなくなることがあるのなら
全く意味が無いので、WebBrowserを使用しましょう。
調べている最中なのですが、なんとなく出来そうも無い様なのですが
WebBrowserで入力を作成した場合、EnterやFキーの判定は出来ないので
しょうか、また背景色を変えることも出来ないのでしょうか。
> 全く意味が無いので、WebBrowserを使用しましょう。
余力があれば、それを UserControlでカプセル化すると、
取り扱いが楽になりますね。
> WebBrowserで入力を作成した場合、EnterやFキーの判定は出来ないのでしょうか
可能です。onkeydown/onkeypress/onkeyupイベントが利用できます。
HTML要素のイベントを取得するには、MSHTML.TLB を参照設定した上で、最初の
Private Text1 As Object
の部分を、
Private WithEvents Text1 As HTMLTextAreaElement
などのようにすればOKです。
Private Function Text1_onkeypress() As Boolean
Dim Evt As Object
Set Evt = Text1.Document.parentWindow.event
Debug.Print "onkeypress::",
Debug.Print "キーコード="; Evt.keyCode,
Debug.Print "Ctrl="; Evt.ctrlKey,
Debug.Print "Alt="; Evt.altKey,
Debug.Print "Shift="; Evt.shiftKey
Evt.cancelBubble = False
Evt.returnValue = True
Text1_onkeypress = True
End Function
あるいは、「既定のメソッド」を持ったクラスを作成して、
そのインスタンスを Text1.onkeypress に Set するという
方法もあります。(この場合は MSHTML.TLB は不要です)
# この、「既定メソッドをクラスをSetする方法」の場合は、
# イベント発生時に、そのクラスの既定のメソッドが
# 呼び出されることになります。
> また背景色を変えることも出来ないのでしょうか。
CSSで変更できます。プログラム的に変更するには、
styleプロパティもしくは runtimeStyleプロパティを使います。
MsgBox "標準色の「赤」"
Text1.runtimeStyle.background = "red"
MsgBox "Webカラーの「雪色」"
Text1.runtimeStyle.background = "snow"
MsgBox "システムカラーの「Window背景色」"
Text1.runtimeStyle.background = "window"
MsgBox "システムカラーの「ボタン色」"
'Text1.runtimeStyle.background = "ThreeDFace" 'ThreeDFaceとButtonFaceは
Text1.runtimeStyle.background = "ButtonFace" 'どちらも同じ意味になります
MsgBox "RGBカラーでの指定「#ffffcc」"
Text1.runtimeStyle.background = "#ffffcc"
なお、現在の設定値を知りたい場合は、currentStyleプロパティです。
MsgBox "現在の色は、" & Text1.currentStyle.backgroundColor & "です。"
有難う御座います、魔界の仮面弁士様
質問ばかりですみません、VB初めてからまだあまりたっていないもので
なにをどう探したら良いのかわからないもので、すみません。
Enterキーは、Debug.Printに出力されるのですがFキーが出力
されないのですが、Fキーは判定できないのでしょうか
WebBrowserで入力項目へ、カーソルをセット(SetFocus)
するには、どうすればいいのでしょうか
入力モードを漢字にするには、どうすればいいのでしょうか
UserControlでカプセル化するには、何かよい参考書は有りませんか。
MSHTMLのonkeypressイベントは、
『文字キーの押下を判定するためのイベント』
です。ファンションキーや 矢印キーは文字キーでは無いため、
それらを拾う事はできません。
そうしたキーを拾いたい場合は、かわりに MSHTMLの
onkeyup/onkeydownイベントを利用してください。
これは、VBのKeyPressイベント、およびKeyUp/KeyDownイベントにも
言えることです。
> UserControlでカプセル化するには、何かよい参考書は有りませんか。
とりあえずは、MSDNライブラリ…ですかね。目次から
[Visual Basic ドキュメント]
+[Visual Basic の使用方法]
+[コンポーネント ツール ガイド]
+[ActiveX コンポーネントの作成方法]
+[ActiveX コントロールの作成手順]
のサンプルを、一通り真似てみれば、ある程度の流れは
掴めるかと思います。
………で。面白そうなのでUserControl化してみました。
http://www.ocv.ne.jp/~oratorio/windev/vb/UnicodeTextBox.lzh
# WinXP + IE6環境でしかテストしていません。
# 他の環境で正しく動くかどうかは未検証です。
大変お世話になっています、魔界の仮面弁士様
UserContro化までしていただき有難う御座います。
UserContro化して頂いたモジュールでKeyDown時の
キー判定の仕方が解らないので教えていただけないでしょうか
すべてやって頂いてしまい申し訳ありません。
先の UnicodeTextBox.lzh サンプルの事であれば、
引数のEventObjectが、DHTMLの「eventオブジェクト」を
返しますので、そのプロパティを利用してください。
例えば、EventObject.keyCode が vbKeyF2 を返すなら、
F2キーが押された事になりますし、Shiftキーが押されていれば、
EventObject.shiftKey が True を返します。
なお、WebBrowserコントロールを使わない方法としては、
riched20.dllのリッチエディットコントロールを
利用するという手法があります。
こちらの方法の場合は、コントロールの作成のために CreateWindow API、
文字列の取得と設定にEM_GETTEXTEX / EM_SETTEXTEX メッセージを
利用する事になります。キー押下のイベント等はサブクラス化で。
大変お世話になっています、魔界の仮面弁士様
もう少しで私のやりたい事は、完成しそうなのですが、
もう少し教えて下さい。
1.ユーザーコントロールへカーソルが行くと一回Tabキーを
押さないと、入力もFキー判定もできないのはどの辺りを修正すれば
良いのでしょう
2.ユーザーコントロールのKeyDownをEnterで抜けると正常に動作するのですが、
Fキーで抜けると表示が消えたりしてしまうのですがどの辺りを
修正すれば良いのでしょう
3.IMEモードを漢字に設定するには、何を追加したら良いのでしょう
============================
> 1. 一回Tabキーを押さないと……
UserControlのソース中の
Private Sub UserControl_GotFocus()
というイベントを、
Private Sub UserControl_EnterFocus()
に変更してください。
============================
> 2. Fキーで抜けると表示が消えたりしてしまう……
質問の[Enterで抜ける][Fキーで抜ける]という意味がわかりません。
ただ、表示が消えるというからには、おそらく F5キーを押しているのでは
ないでしょうか? F5は、ブラウザの[再読込/更新]を行う事になるので、
WebBrowserの内容が初期状態(表示が空の状態)に戻ってしまいます。
この場合、キーの入力をキャンセルさせるための処理が必要になります。
Private Sub onkeydown_OnEvent(ByVal e As Object)
RaiseEvent KeyDown(e)
If e.keyCode = vbKeyF5 Then
e.keyCode = 0 '「イベントを起こしたキーは無い」という状態にする
e.returnValue = False 'このイベント(onkeydown)の処理をキャンセルする
End If
End Sub
実際には、F5以外にもキャンセルさせた方が良い組み合わせが幾つかありますので、
必要に応じて、それらのキー入力もキャンセルさせるようにしてみて下さい。
例えば、キャンセルさせるべきキーとしては、このような物があります。
F5: 更新 → 初期状態に戻ってしまう。
Ctrl+F5: 強制更新 → 初期状態に戻ってしまう。
F6、またはCtrl+Tab: 次フレーム移動 → フォーカスを失ってしまう。
F11: 全画面表示 → WebBrowserの動作が一瞬止まるので、連続入力できなくなる。
Ctrl+N: 新規ウィンドウ → InternetExplorerが起動してしまう。
Ctrl+P: 印刷 → 印刷ダイアログが表示されてしまう。
============================
> 3.IMEモードを漢字に設定するには……
CSSで変更できます。プログラム的に変更するには、
styleプロパティもしくは runtimeStyleプロパティを使います。
UserControlのソース中の、「Private Sub Initialize()」内を
以下のように修正してみて下さい。
With TextControl.runtimeStyle
.imeMode = "active" '☆☆☆この行を追加☆☆☆
.Width = "100%"
.Height = "100%"
End With
なお、imeModeプロパティで指定できる文字列は、以下の4種です。
"auto" 既定値です。IMEの制御を行いません。
"acitve" IMEをOnにします。
"inactive" IMEをOffにします。
"disabled" IMEを使用不可にします。
http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/imemode.asp
この設定部を、UserControlに「IMEModeプロパティ」として実装させると、
良いかもしれませんね。
============================
バグ修正
1つ目。
UserControl中の onchange_OnEvent イベントにて、
mstrText = TextControl.Text
という記述がありますが、これは、
mstrText = TextControl.Value
の間違いです。
2つ目。
UserControlに、以下のコードを追加してください。
無くても動作しますが、一応保険として。
Private Sub UserControl_Initialize()
Set WB = WebBrowser1.Object
End Sub
3つめ。
UserControl_ReadPropertiesイベントプロシージャの最後と、
UserControl_WritePropertiesイベントプロシージャの最後に、
それぞれ、次の行を追加してください。これらが無いと、
BackColorプロパティの設定が保存されません。
UserControl_ReadPropertiesプロシージャに追加:
TextControl.runtimeStyle.backgroundColor = PropBag.ReadProperty("BackColor", "")
UserControl_WritePropertiesプロシージャに追加:
PropBag.WriteProperty "BackColor", TextControl.runtimeStyle.backgroundColor
============================
有難う御座いました、魔界の仮面弁士様
今回の修正でとりあえずやりたい事ができるように成りましたが、
以下の3点について教えてください
1.クラスモジュール追加時、以下のメッセージを表示
'UnicodeTextBoxEvent'は、この種類のプロジェクトではPublicに設定できません。この
アイテムはPrivateに変更されます。
2.ユーザーコントロール追加時、以下のメッセージを表示
'UnicodeTextBox'は、この種類のプロジェクトではPublicに設定できません。このアイテムは
Privateに変更されます。
とりあえず動いているので、上記2点は特に問題は無いのでしょうか?
3.UnicodeTextBoxを設定してあるフォームを別プロジェクトに追加しようとすると、いかのエラーログが出力されます
行 24: クラス 蔵書管理.UnicodeTextBox(コントロール txt_著者名) はロードされていません。
行 133: クラス 蔵書管理.UnicodeTextBox(コントロール txt_作品名) はロードされていません。
行 30: プロパティ名 _ExtentX(txt_著者名) が不正です。
行 31: プロパティ名 _ExtentY(txt_著者名) が不正です。
行 139: プロパティ名 _ExtentX(txt_作品名) が不正です。
行 140: プロパティ名 _ExtentY(txt_作品名) が不正です。
行 141: プロパティ名 Text(txt_作品名) が不正です。
> 'UnicodeTextBoxEvent'は、この種類のプロジェクトではPublicに設定できません。
> 'UnicodeTextBox'は、この種類のプロジェクトではPublicに設定できません。
OCXにコンパイルして使うのではなく、標準EXE内に
組み込んで使おうとしているのですね。
その場合、あのサンプルでは
・ユーザコントロールの PublicプロパティがTrueになっている。
・クラスモジュールの Instancingプロパティが「Private以外」になっている。
という事が原因で、そのような警告が表示されます。
> とりあえず動いているので、上記2点は特に問題は無いのでしょうか?
問題ありません。PublicやInstancingのプロパティ設定というのは、
ActiveXコンポーネントを作成する際に、そのクラス/コントロールを
他プロジェクトから利用できるようにするか否かを設定するための物です。
標準EXEでは、これらを「パブリック」な値に設定する事ができないので、
VBが強制的に「プライベート」な設定値に修正したというわけです。
> UnicodeTextBoxを設定してあるフォームを別プロジェクトに追加しようとすると、
フォームを追加する前に、そのプロジェクトに、
クラスモジュール'UnicodeTextBoxEvent'と
ユーザコントロール'UnicodeTextBox' を追加しておいて下さい。
これらがプロジェクトに含まれていない状態で、フォームだけ
別プロジェクトに追加しようとすると、そのようなエラーが発生します。
有難う御座います、魔界の仮面弁士様
フォームを追加する前に、そのプロジェクトに、
クラスモジュール'UnicodeTextBoxEvent'と
ユーザコントロール'UnicodeTextBox' を追加して、早速試してみたのですが、
フォームを別プロジェクトから追加すると、UnicodeTextBoxが
pictureBoxに変わってしまいました
コントロールの参照に失敗した場合、そのコントロールは
PictureBoxに置き換えてロードされます。
で、失敗する原因はプロジェクト名にあります。
例えば私のサンプルコードを例に取れば、フォームが利用している
コントロールは、「TextBoxW.UnicodeTextBox」です。
(*.frmファイルをメモ帳で開くと、このような記述が見つかるかと思います)
つまり、「TextBoxWというプロジェクト上のUnicodeTextBoxコントロール」を
追加しようとしたが、TextBoxWが見つからなかった…という事だと思います。
なので、このフォームを他のプロジェクトで開く場合は、
案1) プロジェクトグループに、TextBoxW.vbp を追加しておく
案2) TextBoxW.vbp をコンパイルしてTextBoxW.ocxにし、
それをプロジェクトに追加しておく
案3) 自プロジェクトの名前を TextBoxW に変更しておき、
そこに先のUserControlとClassを追加しておく
のいずれかの方法をとすれば、正しく読み込まれると思います。多分。
有難う御座います、魔界の仮面弁士様
OCXにコンパイルをして使うことにしました。
IMEModeプロパティとして設定しようとしているのですが、
項目名を入力後ピリオド入力した時の一覧には表示されるのですが
実際の入力モードが変わらないので、どのように設定すれば良いのですか。
> 実際の入力モードが変わらないので、どのように設定すれば良いのですか。
実装方法は幾つかありますが、たとえば、
Public Enum IMEModeConstants
auto
active
inactive
disabled
End Enum
という列挙型をUserControl上に配置した上で、
Public Property Get IMEMode() As IMEModeConstants
Select Case LCase(TextControl.currentStyle.IMEMode)
Case "active"
IMEMode = active
Case "inactive"
IMEMode = inactive
Case "disabled"
IMEMode = disabled
Case Else
IMEMode = auto
End Select
End Property
Public Property Let IMEMode(ByVal vNewValue As IMEModeConstants)
Select Case vNewValue
Case auto
TextControl.runtimeStyle.IMEMode = "auto"
Case active
TextControl.runtimeStyle.IMEMode = "active"
Case inactive
TextControl.runtimeStyle.IMEMode = "inactive"
Case disabled
TextControl.runtimeStyle.IMEMode = "disabled"
Case Else
TextControl.runtimeStyle.IMEMode = ""
End Select
UserControl.PropertyChanged "IMEMode"
End Property
のようなプロパティ定義を記述し、そしてさらに UserControlの
Read(Write)Properties イベントにて、以下の記述を追加してみるとか。
ReadProperties イベント:
TextControl.runtimeStyle.IMEMode = PropBag.ReadProperty("IMEMode", "")
WriteProperties イベント:
PropBag.WriteProperty "IMEMode", TextControl.currentStyle.IMEMode
有難う御座います、魔界の仮面弁士様
IMEModeの変更は出来たのですが、
さいしょにカーソルが移動した時にモードが変わらないのですが
ユーザーコントロールを変更してコンパイルするとリコンパイルすれば良いのですか、
それとも貼り付け変えなければいけないのでしょうか
> さいしょにカーソルが移動した時にモードが変わらないのですが
当方では、先のコードでモードが正しく切替わっていますが…何故でしょうね。
もしかしたら、styleオブジェクトのimeModeプロパティが正しく修正されて
いないのではないでしょうか? UserControl中の imeModeの設定を行うコードの部分が
正しく実行されているか、ステップ実行しながら確認してみては如何でしょう。
> ユーザーコントロールを変更してコンパイルするとリコンパイルすれば良いのですか、
「変更してコンパイルするとリコンパイルする」という意味がわかりません。
> それとも貼り付け変えなければいけないのでしょうか
コントロールを修正したとしても、それがバイナリ互換を保っている限りは、
コンパイルしなおすだけで十分です。利用側は修正の必要はありません。
しかし、バイナリ互換性が無くなるような修正をした場合は、それは
「名前が一緒なだけで、実際には全く別のコントロール」として
認識されますので、利用側も、コントロールの貼り直しが必要になります。
大変お世話になってます、魔界の仮面弁士様
すみません、用事で出かける前に慌てて打ったので変な文章になってしまってました、本当は
ユーザーコントロールを変更したら、利用側はコンパイルし直すだけで良いのか
再度貼り付けなければならないのか
と言う質問をしたかったのです。
IMEModeは、明日にでもチェックしてみます。
大変お世話になってます、魔界の仮面弁士様
IMEModeの件は、モード設定場所が悪かったようで、設定場所を変更したら
ちゃんと切り替わりました。
IMEModeを漢字に変更して、次項目(データコンボ)等のIMEModeプロパティを
持っていない項目に移動した時に、漢字モードを解除するにはどうすればいいのですか
ツイート | ![]() |