2

RichTextBox コントロールを拡張して、ネイティブの RichEdit クラスで提供されていない機能の多くを実装しました。

コントロールがウィンドウにラップするように設定されている場合、またはプリンターにラップするようにコントロールが設定されている場合、コントロールのサイズが変更されたときに水平スクロールバーが表示されないにもかかわらず、表示されるという問題が発生しています。

wordwrap を none にして元に戻すと問題は解決するようですが、プリンターにラップする場合は比較的遅くなる可能性があります (つまり、すべての Resize イベントで呼び出すには遅すぎる)。

ここに私のワードラップコードがあります:

   private void ChangeWordWrap(WordWrap wordWrap)
    {   
        switch (wordWrap)
        {
            case WordWrap.NoWrap:
                {
                    User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_SETTARGETDEVICE, 0, 1);
                    break;                        
                }
            case WordWrap.WrapToPrintDocument:
                {
                    using (Graphics g = PrintDocument.PrinterSettings.CreateMeasurementGraphics(PrintDocument.DefaultPageSettings))
                    {
                        int lParam = ConvertEx.HundredthInchToTwips((PrintDocument.DefaultPageSettings.Bounds.Width - PrintDocument.DefaultPageSettings.Margins.Left - PrintDocument.DefaultPageSettings.Margins.Right));
                        IntPtr wParam = g.GetHdc();
                        User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_SETTARGETDEVICE, wParam, lParam);
                        g.ReleaseHdc();
                    }
                    break;                                                
                }
            case WordWrap.WrapToControl:
                {
                    User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_SETTARGETDEVICE, 0, 0);
                    break;
                }
        }
    }

当初、問題はグラフィック ハンドルを解放しているという事実に関連していると考えていましたが、コントロールにラップしていてハンドルが不要な場合にも問題が発生します。

スクリーンショットの追加:

正しい動作:

代替テキスト http://www.charltonfamily.net/temp/RTB_EM_SETTARGETDEVICE/WrapToPrinter_Correct_Horizo​​ntal_Scrollbar.png

不適切な動作 (フォームのサイズを非常にわずかに変更した後):

代替テキスト http://www.charltonfamily.net/temp/RTB_EM_SETTARGETDEVICE/WrapToPrinter_Insensitive_Horizo​​ntal_Scrollbar.png

ウィンドウへのラップ/ラップなしのコードは、 http://msdn.microsoft.com/en-us/library/bb774282( VS.85 ).aspx のコメントからのものです。

::SendMessage(hwnd, EM_SETTARGETDEVICE, NULL, 0) を呼び出すとテキストがウィンドウにラップされ、::SendMessage(hwnd, EM_SETTARGETDEVICE, NULL, 1) はワードラップを完全に無効にします。これが他の場所に文書化されているかどうかはわかりません。

私のp /呼び出し:

    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

関連する定数:

    public const int WM_USER = 0x400;
    public const int EM_SETTARGETDEVICE = (WM_USER + 72);

編集:

私はこれをさらに調査しており、コントロールのサイズが変更されたときに、.NET RichTextBox コントロールがおそらく間違った値で SetScrollRange() を送信していると思います。EM_SETTARGETDEVICE メッセージについて必ずしも知っているとは限らないため、これは理にかなっています。

サイズ変更後におそらく SetScrollRange() または同様のものを実行できますが、私の問題は、正しい値が何であるか、またはそれを理解する方法がわからないことです。

私が気付いたもう 1 つのことは、問題が発生しているときに、実際にテキストをラップするサイズにコントロールのサイズを変更できることです。この時点で、スクロールバーは機能する状態に戻り、ワードラップが循環しないまでサイズを変更して元に戻すことができます。

編集:(以下の機能しない回答にも詳細があります)

コントロールのサイズが変更されるとサイズが変更されるため、EM_GETRECT は実際に必要なものではないようです。MSDN の説明は次のとおりです。

EM_GETRECT メッセージ

エディット コントロールの書式設定四角形を取得します。書式設定四角形は、コントロールがテキストを描画する制限四角形です。制限する四角形は、編集コントロール ウィンドウのサイズとは無関係です。このメッセージは、エディット コントロールまたはリッチ エディット コントロールのいずれかに送信できます。

私の最初の理解では、これはテキスト全体の四角形であり、それから、クライアント ウィンドウが書式設定用の四角形よりも小さいため、スクロールバーを表示する必要があるかどうかを判断できます。

この書式設定用の四角形の本当の目的は、テキストをエディット コントロール (余白) よりも小さい領域に表示することです。

新しい質問:

では、EM_GETRECT で得られると思っていた長方形はありますか? テキストの幅 (画面からはみ出す部分を含む) を教えてくれる四角形は? たとえば、400px のコントロールと 800px の長さのテキスト行がある場合、800px の値を取得して、それをコントロールの幅と比較し、スクロールバーの表示/非表示を比較できるようにします。

実際には、オフ コントロール テキストの長さはあまり気にしませんが、IFテキストがコントロールの境界を超えていることを知りたいと思っています。

これまでご協力いただきありがとうございました。

4

3 に答える 3

2

私はあなたのコードを試していません.P/Invoke宣言なしで実行するのは簡単ではありません. SendMessage の LPARAM 引数宣言は間違っているように見えますが、IntPtr である必要があります。WPARAM に 0 を渡してもコンパイルされません。何をしたかわかりません。

SendMessage() の戻り値を確認してください。RichEdit が引数に満足していない場合は、IntPtr.Zero が返されます。デバイス コンテキスト ハンドルに 0 を渡すことは、SDK ドキュメントに許容値として記載されていないため、画面の HDC を渡す必要がある場合があります。Control.CreateGraphics() から簡単に取得できます。

また、水平スクロールバーを表示したくない理由もわかりません。プリンターの WYSIWYG モードに切り替えたときに表示されると思います。

于 2009-12-13T15:03:56.300 に答える
0

私はある種の機能を持っていますが、それは私が本当に望んでいるものではありません.

私が本当にやりたいことは、RichTextBox に私がやりたいことをさせることです。代わりに、RichTextBox に必要なことをさせてから、事後に修正しようとしています。これはおしゃべりな解決策であり、スクロールバーが点滅することがあります。

これが私がやっていることです:

SCROLLINFO scrollinfo = new SCROLLINFO();
scrollinfo.cbSize = Marshal.SizeOf(scrollinfo);
scrollinfo.fMask = ApiConstants.SIF_ALL;
bool flag1 = User32.GetScrollInfo(_RichTextBox.Handle, ApiConstants.SB_HORZ, ref scrollinfo);

Logging.LogMessage("Resize - ScrollInfo: Max: " + scrollinfo.nMax + " Min: " + scrollinfo.nMin + " Page: " + scrollinfo.nPage + " Pos: " + scrollinfo.nPos + " TrackPos: " + scrollinfo.nTrackPos + " || RichtTextBox.RightMargin == " + _RichTextBox.RightMargin + " || RichTextBox.WordWrap == " + WordWrap + " / " + _RichTextBox.WordWrap + " Size: " + Size + " ClientRectangle: " + _RichTextBox.ClientSize);

switch (WordWrap)
{
    case WordWrap.WrapToControl:
    {
        if (scrollinfo.nMax > _RichTextBox.ClientSize.Width)
        {
            User32.ShowScrollBar(_RichTextBox.Handle, ApiConstants.SB_HORZ, false);
        }
        break;
    }
    case WordWrap.WrapToPrintDocument:
    {
        if (scrollinfo.nMax > _PrintableWidth)
        {
            User32.ShowScrollBar(_RichTextBox.Handle, ApiConstants.SB_HORZ, false);
        }
        break;
    }
}

条件のロジックWordWrap.WrapToControlが壊れており、修正方法がわかりません。問題は、エラー状態のときに最大スクロールが ClientSize よりも大きいことです。ただし、テキストが実際に画面からはみ出す場合 (左インデントを考慮)、最大スクロールも ClientSize よりも大きくなります。

メッセージを使用してこれを解決できると思いEM_GETRECTますが、さらにテストを行う必要があります。ソリューションが WrapToPrintDocument 条件でも機能する可能性はありEM_GETRECTますが、機能する場合、RichTextBox がまだこれを行っていないのはなぜですか? RichTextBox が SCROLLINFO パラメータをどこから取得しているかを知りたいと本当に思っています。そうすれば、2 番目の「修正」メッセージを必要とせずに、RichTextBox コントロールに必要なことを実行させることができるからです。

注: スクロールバーを非表示にした後、RichTextBox がその部分を適切に処理するため、スクロールバーを表示するケースは必要ありません (ため息)

編集:

コントロールのサイズが変更されるとサイズが変更されるため、EM_GETRECT は実際に必要なものではないようです。MSDN の説明は次のとおりです。

EM_GETRECT メッセージ エディット コントロールの書式設定用の四角形を取得します。書式設定四角形は、コントロールがテキストを描画する制限四角形です。制限する四角形は、編集コントロール ウィンドウのサイズとは無関係です。このメッセージは、エディット コントロールまたはリッチ エディット コントロールのいずれかに送信できます。

私の最初の理解では、これはテキスト全体の四角形であり、それから、クライアント ウィンドウが書式設定用の四角形よりも小さいため、スクロールバーを表示する必要があるかどうかを判断できます。

この書式設定用の四角形の本当の目的は、テキストをエディット コントロール (余白) よりも小さい領域に表示することです。

新しい質問:

では、EM_GETRECT で得られると思っていた長方形はありますか? テキストの幅 (画面からはみ出す部分を含む) を教えてくれる四角形は? たとえば、400px のコントロールと長さ 800px のテキスト行がある場合、800px の値を取得して、それをコントロールの幅と比較し、スクロールバーを表示する/表示しないようにします。

これまでご協力いただきありがとうございました。

于 2009-12-15T19:33:51.310 に答える
0

EM_SHOWSCROLLBAR メッセージを試しましたか?

または、 サイズ変更前にWM_SETREDRAW (0) を試し、サイズ変更後に WM_SETREDRAW (1) を試すこともできます。

于 2009-12-15T07:21:29.983 に答える