none
TextBox の幅を小さくした場合に EM_SETMARGINS が設定されない RRS feed

  • 質問

  • OS:Windows XP Professional
    開発環境:Visual Studio 2005
    言語:Visual Basic

     

    こんにちは、ダッチです。

     

    <背景>

    TextBox を左右に画像を表示できるように拡張しています。

     

    <現象>

    画像の表示領域を確保するために EM_SETMARGINS(&HD3) を SendMessage 関数を使用して TextBox に送信しました。
    送信した時は正常に余白が設定されているのですが、TextBox のテキストが表示領域を超えている場合に、末尾にキャレットを移動してから先頭にキャレットを戻すと、設定した余白部分にキャレットが移動されてしまいます。正常に動作していれば余白部分にキャレットは移動しないはずです。


    この現象は TextBox の Size(Width) を初期値 (100) より小さくしている場合に発生しているようです。

     

    .NET Framework 1.1 と 2.0 で現象が発生するのを確認しました。それ以降のバージョンは持っていないので確認していません。

     

    <質問>

    TextBox の幅を 100 より小さくした場合でも正常に EM_SETMARGINS で余白を設定する方法はありませんでしょうか?
    EM_SETMARGINS にこだわっているわけではありません。他の方法で余白を作ることが出来ればそれでも問題ありません。

     

    ※ TextBox を Multiline での使用は想定してません。必ず単一行であるもとのして考えています。

     

    <現象発生手順>

    現象を確認できる手順を次に示します。

     

    Form(Form1) に TextBox(TextBox1) を貼り付けてある状態です。

     

    Code Snippet

    Imports System.Runtime.InteropServices

    Public Class Form1

    #Region " P/Invoke "

        <DllImport("user32", CharSet:=CharSet.Auto)> _
        Private Shared Function SendMessage( _
            ByVal hwnd As IntPtr, _
            ByVal wMsg As Integer, _
            ByVal wParam As Integer, _
            ByVal lParam As Integer _
            ) As Integer
        End Function

        Private Const EC_LEFTMARGIN As Integer = &H1
        Private Const EM_SETMARGINS As Integer = &HD3

    #End Region

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.TextBox1.Text = "あいうえおかきくけこ"
            Me.TextBox1.Width = 60
            SendMessage(Me.TextBox1.Handle, EM_SETMARGINS, EC_LEFTMARGIN, 16)
        End Sub

    End Class

     

     

    TextBox1 にフォーカスを設定してから、[End] キー、[Home] キーの順で入力すると現象がわかるかと思います。

     

    よろしくお願いします。

    2008年5月11日 5:09

回答

  • TextBox で困ったときはRichTextBox を使えって、ばっちゃが。

    2008年5月11日 7:25
  • エクスプローラのアドレスバーはSpy++で見ると、左端のアイコンを除いた部分がEditになっています。

    つまり、1つのEdit(≒TextBox)で実現されているわけではないようです。

    VBでいくとユーザーコントロール的な作りになっています。

     

    TextBox単体でもオーナードローでごしごし書けば実現できそうですが、

    キャレットやIME制御などが違和感なくできるか不安があります。

    でも、趣味と言うことなのでチャレンジしてみても面白いかもしれませんね。

     

    業務ならユーザーコントロールで難なく作成することをお奨めするところです。

     

    私の意見をまとめると以下の通りです。

    ・TextBoxで実現するにはオーナードローになりそうだけど、

    いろいろごしごし書く必要がありそうだし、それでも実現できるか不明。

    なのでお奨めできない。

    ・ユーザーコントロールを使えば同じ要件が簡単に実現できるのでお奨め。

    ・趣味ならTextBoxでがんばるのもあり。業務ならユーザーコントロール。

     

    ところで、ButtonなどにあるPaddingプロパティはなぜTextBoxでは使えないんでしょうか・・・?

    2008年5月12日 2:42
  •  ダッチ さんからの引用

    そういうことだったんですか。
    でも、これってバグのように見えますね。

    言い方がまずかったのですが、「そのようになっています」というのは仕様という意味ではなく、そのように動いているようですと言う事実を伝えたかったものです。

    ドキュメントで触れられていないので不具合だと、今のところ思っています。

    2008年5月12日 13:59
    モデレータ

すべての返信

  • TextBox で困ったときはRichTextBox を使えって、ばっちゃが。

    2008年5月11日 7:25
  •  ダッチ さんからの引用

    .NET Framework 1.1 と 2.0 で現象が発生するのを確認しました。それ以降のバージョンは持っていないので確認していません。

    バージョンに関係ありません。というより、そもそも.NET Frameworkは関係ありません。

    MFCのダイアログアプリでも容易に再現します。

     

    手法の見直しの方向で考えるしかなさそうです。

    2008年5月11日 7:44
    モデレータ
  • 回答ありがとうございます。

     

     Hongliang さんからの引用
    TextBox で困ったときはRichTextBox を使えって、ばっちゃが。

    RichTextBox だと幅を小さくしても現象は発生しませんでした。(さすが知恵袋です)

    でも、今回はどうしても TextBox で実現したいと思っております。

     

     Azulean さんからの引用
    MFCのダイアログアプリでも容易に再現します。

    MFC のことはよくわからないのですが、.NET Framework の TextBox は Windows OS で用意されている EditControl をラップしていると認識しています。その EditControl で現象が再現するということでしょうか。

    Web で検索などして調べたのですが、こういった現象が発生するという情報を見つけられませんでした。

    昔からこの現象が発生することが知られているのであれば、なにか回避策などあってもよさそうなんですが

     

     Azulean さんからの引用
    手法の見直しの方向で考えるしかなさそうです。

    結構前から TextBox に画像を表示しようと考えていて、やっと EM_SETMARGINS というのを見つけました。それがダメとなると、どうしようもなくなってしまいます。何かいいアイディアなどはありませんでしょうか?

    2008年5月11日 12:22
  •  ダッチ さんからの引用

    MFC のことはよくわからないのですが、.NET Framework の TextBox は Windows OS で用意されている EditControl をラップしていると認識しています。その EditControl で現象が再現するということでしょうか。

    そういうことです。

    WindowsのEDITコントロール自体がそのようになっています。

    Vista、XP問わず、再現します。

     

     

    回避策あるいは別のプランはちょっと出てこないです、申し訳ない。

    2008年5月11日 13:58
    モデレータ
  • こんにちは。

     

    TextBoxとPictureBoxを組み込んだユーザーコントロールを作成すればいいのではないですか?

    TextBoxにこだわる事情があるようですが、ユーザーコントロールでもだめですか?

     

    TextBoxを継承したカスタムコントロールにするという手もあります。

    2008年5月12日 0:42
  • 回答ありがとうございます。

     

     Azulean さんからの引用
    WindowsのEDITコントロール自体がそのようになっています。
    Vista、XP問わず、再現します。

    そういうことだったんですか。
    でも、これってバグのように見えますね。

     

     銀漢 さんからの引用
    TextBoxとPictureBoxを組み込んだユーザーコントロールを作成すればいいのではないですか?
    TextBoxにこだわる事情があるようですが、ユーザーコントロールでもだめですか?

    趣味で TextBox を拡張しようといろいろやってます。
    その中の一つがこの画像を表示するというものです。
    ですので TextBox で実現したいです。

     

     銀漢 さんからの引用
    TextBoxを継承したカスタムコントロールにするという手もあります。

    はい、TextBox を継承して拡張しようと考えています。
    イメージとしてはエクスプローラのアドレスバーみたいにしたいと思っています。
    あれは左側にアイコンが表示されていますよね。
    後で完成イメージの画像をアップしようと思います。

     

    2008年5月12日 1:55
  • エクスプローラのアドレスバーはSpy++で見ると、左端のアイコンを除いた部分がEditになっています。

    つまり、1つのEdit(≒TextBox)で実現されているわけではないようです。

    VBでいくとユーザーコントロール的な作りになっています。

     

    TextBox単体でもオーナードローでごしごし書けば実現できそうですが、

    キャレットやIME制御などが違和感なくできるか不安があります。

    でも、趣味と言うことなのでチャレンジしてみても面白いかもしれませんね。

     

    業務ならユーザーコントロールで難なく作成することをお奨めするところです。

     

    私の意見をまとめると以下の通りです。

    ・TextBoxで実現するにはオーナードローになりそうだけど、

    いろいろごしごし書く必要がありそうだし、それでも実現できるか不明。

    なのでお奨めできない。

    ・ユーザーコントロールを使えば同じ要件が簡単に実現できるのでお奨め。

    ・趣味ならTextBoxでがんばるのもあり。業務ならユーザーコントロール。

     

    ところで、ButtonなどにあるPaddingプロパティはなぜTextBoxでは使えないんでしょうか・・・?

    2008年5月12日 2:42
  • 回答ありがとうございます。

     

    まず完成イメージですがこのようになります。

    TextBox の内側に画像が表示されるところがポイントです。

     

     銀漢 さんからの引用
    ・TextBoxで実現するにはオーナードローになりそうだけど

    オーナードローで画像を表示する部分は出来ているのですが、テキストの部分まで描画となると辛いですね。出来たとしても手間がかかりすぎてバグを作りこみそうです怖いです。

     

     銀漢 さんからの引用
    ・ユーザーコントロールを使えば同じ要件が簡単に実現できるのでお奨め。

    「簡単」に実装できる自信がありませんが、エクスプローラのアドレスバーも同じような手法なようですので、出来そうな感じがします。ただ TextBox を継承して作成されたコントロールでないのが辛いところです。

     

    どちらにしても TextBox に画像を表示するのは難しいことを改めて感じました。

    一応 TextBox の幅を狭くしない限りは問題なさそうに見えますので、制限付きにしようかと思います。

     

    まだアイディアや回避策などお持ちの方もいらっしゃるかもしれませんので、ある程度時間が経過してから[回答済み]にしたいと思います。

     

     銀漢 さんからの引用
    ところで、ButtonなどにあるPaddingプロパティはなぜTextBoxでは使えないんでしょうか・・・?

    これはぜひとも TextBox にも実装して欲しいですね。

    EditControl がどうのこうのというのは関係なしに .NET Framework の TextBox だからこういう事が出来るというのがあれば魅力的に思います。

    2008年5月12日 13:50
  •  ダッチ さんからの引用

    そういうことだったんですか。
    でも、これってバグのように見えますね。

    言い方がまずかったのですが、「そのようになっています」というのは仕様という意味ではなく、そのように動いているようですと言う事実を伝えたかったものです。

    ドキュメントで触れられていないので不具合だと、今のところ思っています。

    2008年5月12日 13:59
    モデレータ
  • 回答ありがとうございます。

     

     Azulean さんからの引用
    ドキュメントで触れられていないので不具合だと、今のところ思っています。

    そういうことであれば、後でフィードバックに報告しようと思います。

    でもバグだとしたら随分長いこと放置されてきたバグのように見えますね。

    2008年5月12日 14:31
  • フィードバッグに報告しました。

     

    TextBox の幅を狭くした場合に EM_SETMARGINS が設定されません

    https://connect.microsoft.com/VisualStudioJapan/feedback/ViewFeedback.aspx?FeedbackID=343748

    2008年5月13日 13:08