メソッドを使用DrawReversibleFrame()
すると、ドラッグ操作のオフセットと反転した影が描画されます。メソッドの名前 ( DrawReversibleFrame()
) は、おそらくこれが動作するはずの方法であることを示しているようです (動きを忠実に模倣するのではなく、反転したイメージを描画します)。しかし、私はその反対を望んでいます(そして簡単な方法はないようですDrawFrame()
)。
最初の質問を投稿した後に示された 2 つの例を試してみました。マウスの動きに基づいて四角形を描画するにはどうすればよいですか?
これら 2 つの試みは、次の場所にあります。
..そしてここ:
http://www.switchonthecode.com/tutorials/winforms-painting-on-top-of-child-controls
...しかし、どちらも私にはうまくいきません。
まず第一に、両方の例のイベントで base.* を呼び出すと、それらを実行すると StackOverflows (しゃれは意図されていません) が発生します (多くの場合、StackOverflows がアプリを爆破するために何もする必要さえありません)。
DrawReversibleFrame()
サンプル (上記の 2 番目のリンク)からコードを適応させることができます。ただし、マウスを使用して左右 (左上から右下) にドラッグすると、描画される四角形は右下から始まり、左上に上がります (ただし、反対の方向にドラッグしています。左上から右下へ) -- ただし、移動したサイズ/量は正確に正しいようです。
さらに、描画操作の開始点も正確に正しい場所ではありません。最初の点の少し左と上から開始します。
注:フォームの上に配置された上でPointToScreen()
ドラッグ操作が行われているため、使用しています。TableLayoutPanel
それを使わなければ、描画はまったく行われません。
私のコードは次のとおりです。
public partial class Form1 : Form
{
private bool _IsSelecting = false;
private Point _StartPoint = Point.Empty;
private Rectangle _FrameRect = Rectangle.Empty; //1
public Form1()
{
InitializeComponent();
// DoubleBuffered = true; //makes no apparent difference either way
}
private void tableLayoutPanel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
_IsSelecting = true;
_StartPoint = PointToScreen(e.Location);
_FrameRect = new Rectangle(_StartPoint, Size.Empty);
}
private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
{
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
Point pt = PointToScreen(e.Location);
_FrameRect.Width = _StartPoint.X - pt.X;
_FrameRect.Height = _StartPoint.Y - pt.Y;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
}
private void tableLayoutPanel1_MouseUp(object sender, MouseEventArgs e)
{
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect,
Color.Black, FrameStyle.Dashed);
_IsSelecting = false;
_FrameRect = Rectangle.Empty;
_StartPoint = Point.Empty;
}
}
アップデート
ジョンのコメントに応えて、ここで数学を逆にしました。
_FrameRect.Width = pt.X - _StartPoint.X;
_FrameRect.Height = pt.Y - _StartPoint.Y;
...しかし、ほとんど機能するようになるので、それは私をからかうだけですが、PointToScreen() への呼び出しを PointToClient() に変更すると、さらに悪化します (さらに左と上に、時には長方形が大きすぎます) )。
現在のコードは次のとおりです(長方形は完璧なサイズですが、マウスの左と上から始まります):
private void tableLayoutPanel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
return;
_IsSelecting = true;
_StartPoint = PointToScreen(e.Location);
//_StartPoint = PointToClient(e.Location); //<- this makes it way worse - the rectangle is way too big, and starts even further up and to the left
_FrameRect = new Rectangle(_StartPoint, Size.Empty);
}
private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
{
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
Point pt = PointToScreen(e.Location);
//Point pt = PointToClient(e.Location); //worse
_FrameRect.Width = pt.X - _StartPoint.X;
_FrameRect.Height = pt.Y - _StartPoint.Y;
ControlPaint.DrawReversibleFrame(_FrameRect, Color.Black, FrameStyle.Dashed);
}
private void tableLayoutPanel1_MouseUp(object sender, MouseEventArgs e)
{
if (!_IsSelecting)
return;
ControlPaint.DrawReversibleFrame(_FrameRect,
Color.Black, FrameStyle.Dashed);
_IsSelecting = false;
_FrameRect = Rectangle.Empty;
_StartPoint = Point.Empty;
}
別の更新
注:フォーム上にあるパネル上にある動的に作成されたTableLayoutPanelでマウスダウンを実行しています。
以下のコードを追加したとき、値は 25、次に 146 でした。したがって、うまくいくはずです。Y 値を 146 に変換するときに、TableLayoutPanel の上にあるという事実を補っています。しかし、それでは十分ではありません。 ...???
log.Debug(String.Format("Mouse Down Location.Y = {0}", e.Location.Y));
_StartPoint = PointToScreen(e.Location);
log.Debug(String.Format("Mouse Down PointToScreen Location.Y = {0}", _StartPoint.Y));
さらに別の更新
ここで私の質問への回答を含む長方形の下に TextBoxes を見つけることができました (30 日間で 50 の質問の制限を超えていたため、StackOverflow に新しい質問を投稿できませんでした)。
...しかし、今は別の問題があります:
コード (以下) は、パネル上のすべての TextBox をループ処理するため、その下にあるコントロールを検出し、描画された四角形の下にある正しい数のコントロールを検出します (9 つの TextBox をドラッグすると、9 が検出されます)。
ただし、見つかったものとしてタグ付けされた TextBox は正しいものではありません。ドラッグしたものではなく、TableLayoutPanel の数行下に配置されています。
描画された _FrameRect は PointToScreen() から変換され、textBox.Bounds は RectangleToScreen() から変換されるため、同期する必要がありますが、どういうわけかそうではありません... (これらの絶対位置の変換がなければ相対位置、textBoxes はまったく検出されません)。
private void HighlightAllTextBoxValsBetweenPoints() {
foreach (Control ctrl in tableLayoutPanelGreatgooglyMoogly.Controls) {
var tb = ctrl as TextBox;
if (tb == null)
continue;
if (RectangleToScreen(tb.Bounds).IntersectsWith(_FrameRect)) {
//MessageBox.Show(String.Format("{0}", tb.Name));
tb.BackColor = PSEUDO_HIGHLIGHT_COLOR;
}
}
}
ここでも、適切な数のコントロールが見つかり、それらが「強調表示」されます (backColor プロパティが変更されます) が、適切なコントロールではありません。
最終更新
ここにアップロードされた猫 (または蛙足だと思います) のコードに基づいています。
http://www.c-sharpcorner.com/Forums/Thread/170813/
...コントロールの疑似強調表示を機能させることができました。関連するコードは次のとおりです。
// Declare a rectangle and a point:
Rectangle describedRect;
Point startingPoint;
private bool _IsSelecting = false; // <- already had this
// In the MouseDown event:
_IsSelecting = true;
startingPoint = e.Location;
// In the MouseMove event:
if (!_IsSelecting)
return;
describedRect = Rectangle.FromLTRB(startingPoint.X, startingPoint.Y, e.X, e.Y);
// In the MouseUp event:
if (!_IsSelecting)
return;
HighlightAllTextBoxValsBetweenPoints();
_IsSelecting = false;
private void HighlightAllTextBoxValsBetweenPoints() {
foreach (Control ctrl in tableLayoutPanelGreatGooglyMoogly.Controls) {
var tb = ctrl as TextBox;
if (tb == null)
continue;
if (describedRect.IntersectsWith(tb.Bounds)) {
tb.BackColor = PSEUDO_HIGHLIGHT_COLOR;
}
}
}