Reputation: 10227
I'm trying to set the back color of each TextBox that is within the rectangle defined between a MouseDown and MouseUp event, where the MouseUp event takes place to the right of and below the MouseDown event.
I capture the Points this way:
static readonly Color PSEUDO_HIGHLIGHT_COLOR = Color.Gainsboro;
private Point selectionStart;
private Point selectionEnd;
. . .
private void flowLayoutPanelGreatGooglyMoogly_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
selectionStart = PointToClient(MousePosition);
}
}
private void flowLayoutPanelGreatGooglyMoogly_MouseUp(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
selectionEnd = PointToClient(MousePosition);
HighlightAllTextBoxValsBetweenPoints();
}
}
...and here's the code that should set the BackColor of the TextBoxes "beneath" the virtual rectangle described by the Points:
private void HighlightAllTextBoxValsBetweenPoints() {
TextBox tb;
foreach (Control ctrl in flowLayoutPanelGreatGooglyMoogly.Controls) {
if (ctrl is TextBox) {
tb = (TextBox)ctrl;
if ((tb.Location.X >= selectionStart.X) &&
(tb.Location.Y >= selectionStart.Y) &&
(tb.Location.X <= selectionEnd.X) &&
(tb.Location.Y >= selectionEnd.Y)) {
tb.BackColor = PSEUDO_HIGHLIGHT_COLOR;
}
}
}
}
...but, although the code is being executed, none of the TextBoxes are ever seen as being within those constraints.
It's as if I'm dragging over a map of the good ol' USA, but the troll under the bridge is telling me that Kansas is really in Canada.
My logic is probably mixed-up or backwards (failing to compare the X and Y coordinates correctly), or I'm failing to convert the Points from relative to absolute or vice versa.
The answer was almost perfect (and how was John to know that my FlowLayoutPanel was situated where it was); to get it to work, I just had to add this above his code:
// Have to subtract the Top (Y) value of the Panel
int DeltaFromFormTopToPanelTop = flowLayoutPanelGreatGooglyMoogly.Location.Y;
selectionStart.Y = selectionStart.Y - DeltaFromFormTopToPanelTop;
selectionEnd.Y = selectionEnd.Y - DeltaFromFormTopToPanelTop;
To prevent the coloring/prompting when a user has only selected one control, I had to add this code, too:
if (e.Button == MouseButtons.Left) {
selectionEnd = PointToClient(MousePosition);
if (MouseHasNotMovedFar()) {
return;
}
HighlightAllTextBoxValsBetweenPoints();
PromptForAndAssignInputValue();
}
private bool MouseHasNotMovedFar() {
// The "X" or horizontal, is TextBoxWidth*2 + LabelWidth*1
// The "Y" or vertical, is TextBoxHeight*2
// If the user has moved the mouse less than these between
// MouseDown and MouseUp, they probably have not dragged to
// select multiple TextBoxes.
const int ACCEPTABLE_X_DELTA = 74;
const int ACCEPTABLE_Y_DELTA = 40;
return (selectionEnd.X - selectionStart.X) <= ACCEPTABLE_X_DELTA &&
(selectionEnd.Y - selectionStart.Y) <= ACCEPTABLE_Y_DELTA;
}
Upvotes: 0
Views: 295
Reputation: 6689
There's a few issues.
First - textbox coordinates are relative to the flowLayoutPanel. Therefore your PointToClient must be the same:
selectionStart = flowLayoutPanelGreatGooglyMoogly.PointToClient(MousePosition);
Second - you had a logic bug; the last comparison was reversed. (tb.Location.Y >= selectionEnd.Y)) {
A suggestion to simplify the process and allow dragging in any direction would be to use Rectangles:
private void HighlightAllTextBoxValsBetweenPoints()
{
var selectionBounds = new Rectangle(
selectionStart.X,
selectionStart.Y,
selectionEnd.X - selectionStart.X,
selectionEnd.Y - selectionStart.Y);
foreach (Control ctrl in flowLayoutPanel1.Controls)
{
var tb = ctrl as TextBox;
if (tb == null)
continue;
if (tb.Bounds.IntersectsWith(selectionBounds))
tb.BackColor = PSEUDO_HIGHLIGHT_COLOR;
}
}
Upvotes: 2