DOBON.NETプログラミング道掲示板
(現在 過去ログ1 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33004 / inTopicNo.1)  テキストボックスで画面端で改行したい。
  
□投稿者/ きっず 一般人(1回)-(2015/06/29(Mon) 19:36:27)
  • アイコン環境/言語:[C# Framework4.0] 
    分類:[.NET] 

    はじめまして。
    きっずといいます。
    テキストボックスに文字列を入力した際に
    テキストボックスの端で折れてほしいのですが
    意図しない場所で改行が入ってしまいます。

    現在の設定は
    #####################################
    textbox1.Multiline = True;
    textbox1.WordWrap = True;
    #####################################
    「今日からhttp://www.yahoo.co.jp/amore.php?and=aaaです。」
    という文言を張り付けた際に

    ######################################
    今日からhttp://www.yahoo.co.jp/amore.php?an
    d=aaaです。
    ######################################
    と表示してほしいのですが

    ######################################
    今日から
    http://www.yahoo.co.jp/amore.php?
    and=aaaです。
    ######################################
    となってしまいます。

    解決方法はございますでしょうか。
    よろしくお願いいたします。
引用返信 削除キー/
■33005 / inTopicNo.2)  Re[1]: テキストボックスで画面端で改行したい。
□投稿者/ 魔界の仮面弁士 大御所(973回)-(2015/06/29(Mon) 20:15:32)
  • アイコン
    No33004に返信(きっずさんの記事)
    > textbox1.Multiline = True;
    
    Textbox1.Multiline = True  ' VB (or Visual Studio プロパティ画面)
    textbox1.Multiline = true; // C#
    textbox1.Multiline = True; ???
    
    
    > テキストボックスの端で折れてほしいのですが
    > 意図しない場所で改行が入ってしまいます。
    
    これでどうでしょう。
    
    [System.Runtime.InteropServices.DllImport("user32")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msgId, IntPtr wParam, EditWordBreakProc lParam);
    private delegate int EditWordBreakProc(IntPtr ipch, int ichCurrent, int cch, int code);
    private void Form1_Load(object sender, EventArgs e)
    {
     const int EM_SETWORDBREAKPROC = 0xD0;
     SendMessage(this.textBox1.Handle, EM_SETWORDBREAKPROC, IntPtr.Zero, delegate { return 0; });
     this.textBox1.Text = this.textBox1.Text + '\0';
    }

引用返信 削除キー/
■33006 / inTopicNo.3)  Re[2]: テキストボックスで画面端で改行したい。
□投稿者/ きっず 一般人(2回)-(2015/06/30(Tue) 10:22:17)
  • アイコン魔界の仮面弁士さま

    お返事ありがとうございます!!
    こちらの意図した動きになりました。

    不勉強で申し訳ないのですが
    何故上記の内容を記述することで意図した動きに変わったのでしょうか?
    ご教授頂ければ幸いです。

解決み!
引用返信 削除キー/
■33010 / inTopicNo.4)  Re[3]: テキストボックスで画面端で改行したい。
□投稿者/ 魔界の仮面弁士 大御所(975回)-(2015/06/30(Tue) 18:17:41)
  • アイコン
    追加質問のようなので、解決済みマークを一旦外しておきます。
    
    ■No33006に返信(きっずさんの記事)
    > こちらの意図した動きになりました。
    
    No33005 のサンプルコードは簡易実装です。
    
    受け渡された引数を無視して常に「return 0;」としていますので、
    ダブルクリック時には、単語単位の選択が行えず、
    カーソルが先頭に戻ってしまうという弊害があります。
    
    必要に応じて、適宜修正してみて下さい。
    
    
    > 何故上記の内容を記述することで意図した動きに変わったのでしょうか?
    
    今回使用した EM_SETWORDBREAKPROC メッセージというのは、
    単語の区切りをカスタマイズするためのものです。
    
    これにより、今回問題としていた『テキストの折り返し位置』の他、
    [Ctrl](+[Shift])+[→]キー、あるいはダブルクリックでの
    『文字列選択』の動作が上書きされることになります。
    
    
    この EM_SETWORDBREAKPROC では、単語の区切りをカスタマイズするために、
    EditWordBreakProc というコールバック関数を受け渡す必要があります。
    
    今回は無条件に 0 を return するようにしていますが、本来は
    引数に応じた値を return せねばなりません。このコールバック関数の
    具体的な仕様については、下記の URL を参照してみてください。
    https://msdn.microsoft.com/ja-jp/library/cc410811.aspx
    
    
    なお EditWordBreakProc が働くのは、次回以降の入力・選択に対してです。
    既に入力されている文字列の折り返し位置までは変更されないため、先のコードでは
    Text プロパティに別の文字列を再設定することで、設定が即時反映されるようにしています。
    (なお TextBox は、'\0' 以降の文字列を切り捨てる仕様なため、結果として同じ)
    
    
    
    参考までに、コールバック関数にどのような値が渡されるのかを監視できるようにしてみました。
    
    
    // using System.Runtime.InteropServices;
    
    private enum WorkBreak
    {
        WB_LEFT = 0,
        WB_RIGHT = 1,
        WB_ISDELIMITER = 2,
        WB_CLASSIFY = 3,
    
        // WB_MOVEWORDLEFT = 4,
        // WB_MOVEWORDRIGHT = 5,
        // WB_LEFTBREAK = 6,
        // WB_RIGHTBREAK = 7,
    
        WB_MOVEWORDPREV = 4,
        WB_MOVEWORDNEXT = 5,
        WB_PREVBREAK = 6,
        WB_NEXTBREAK = 7,
    }
    
    [Flags]
    private enum WordBreakFlags
    {
        WBF_CLASS = 0x0F,
        WBF_ISWHITE = 0x10,     // 空白文字
        WBF_BREAKLINE = 0x20,   // 区切り文字
        WBF_BREAKAFTER = 0x40,  // この文字の後での改行を許可
    }
    
    [DllImport("user32")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msgId, IntPtr wParam, EditWordBreakProc lParam);
    private delegate int EditWordBreakProc(IntPtr ipch, int ichCurrent, int cch, WorkBreak code);
    
    private int EditWordBreak(IntPtr ipch, int ichCurrent, int cch, WorkBreak code)
    {
        var srcText = Marshal.PtrToStringAuto(ipch, cch);
        var currentChar = (ichCurrent >= srcText.Length) ? "" : "(" + srcText[ichCurrent] + ")";
    
        var msg = string.Format("モード={0}, 切分位置={1}{2}, 文字列={3}", code, ichCurrent, currentChar, srcText);
        this.listBox1.TopIndex = this.listBox1.Items.Add(msg);
    
        return 0;   // 本来は 0 固定ではなく、引数に応じた値を返すように実装する
        //
        // code == WB_ISDELIMITER の場合:区切り文字なら 1、それ以外なら 0 を返す
        // code == WB_CLASSIFY の場合:WBF_系のフラグ値を返す
        // code が上記以外:単語の開始点のインデックスを返す
    }
    
    private void Form1_Load(object sender, EventArgs e)
    {
        const int EM_SETWORDBREAKPROC = 0xD0;
        SendMessage(this.textBox1.Handle, EM_SETWORDBREAKPROC, IntPtr.Zero, this.EditWordBreak);
        this.textBox1.Text += '\0';
    }
    

引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -