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://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テキストがコントロールの境界を超えていることを知りたいと思っています。
これまでご協力いただきありがとうございました。