1

GetCaretPos() Win32 API を使用して、テキスト ボックスが非表示の場合でも、テキスト ボックスのキャレットの位置を取得したいと考えています。テキストボックスに 1 行しかない場合は問題ないように見えますが、行数が多いほど、キャレットの Y 座標が異なります (GetCaretPos() によって報告されます)。GetCaretPos( によって報告されるキャレットの Y 座標) は常に、キャレットの実際の Y 座標よりも大きくなります。

これは何が原因で、どうすれば修正できますか?

コードは次のとおりです。

[DllImport("user32")]
private extern static int GetCaretPos(out Point p);
[DllImport("user32")]
private extern static int SetCaretPos(int x, int y);
[DllImport("user32")]
private extern static bool ShowCaret(IntPtr hwnd);
[DllImport("user32")]
private extern static int CreateCaret(IntPtr hwnd, IntPtr hBitmap, int width, int height);
//Suppose I have a TextBox with a few lines already input.
//And I'll make it invisible to hide the real caret, create a new caret and set its position to see how the difference between them is.

private void TestCaret(){
   textBox1.Visible = false;//textBox1 is the only Control on the Form and has been focused.
   CreateCaret(Handle, IntPtr.Zero, 2, 20);
   Point p;
   GetCaretPos(out p);//Retrieve Location of the real caret (calculated in textBox1's coordinates)
   SetCaretPos(p.X + textBox1.Left, p.Y + textBox1.Top);
   ShowCaret(Handle);
}

私が言ったように、フォーム上のどこでも、textBox1それが見えない場合、上記のメソッドを呼び出すと、実際の (隠れた) キャレットの正確な位置に偽のキャレットが表示されます。textBox1 が 1 行しかない場合は正常に機能しますが、複数行ある場合は機能しません。

4

1 に答える 1

0

テキスト ボックスは、フォーカスされていないときはキャレットを持ちません (つまり、表示されていないときも同様です)。具体的には、スレッドごとに 1 つのコントロール (「ウィンドウ」) だけがいつでもキャレットを持つことができます。これは、テキスト ボックスがフォーカスされていない、または非表示になっている間、別の方法でキャレットの位置を保存し、再びフォーカスされたときに保存された位置に新しいキャレットを作成する必要があることを意味します。

これにより、次の 2 つのオプションが残ります。

  1. テキスト ボックスがフォーカスを失う前にキャレットの位置を取得して保存します (Leave イベントを使用するか、TextBox クラスから継承するクラスを作成して LostFocus メソッドをオーバーライドします)。

  2. TextBox の SelectionStart (+SelectionLength) プロパティと GetPositionFromCharIndex メソッドを使用して、テキスト ボックスが再びフォーカスされたときにキャレットが作成される位置を見つけます。

于 2014-11-29T12:42:16.483 に答える