Here's the Eyeshot code to simulate the selection style of AutoCAD®. Clicking the mouse will set the pick state to "Pick". When moving the mouse to the right more than 10 pixels, the pick state changes to Enclosed and when moving to the left of the same amount the pick state becomes Crossing. A transparent rectangle is drawn in overlay according to the pick state and when releasing the mouse the selection is performed according to the pick state. Instead of the *Design.SelectionChanged* event, we raise a *CustomSelectionChanged* event with the added and removed entities computed in the *OnMouseUp()*.

- WinForms code:

```
internal class MyDesign : devDept.Eyeshot.Control.Design
{
private enum pickState
{
Pick,
Enclosed,
Crossing
};
private pickState currPickState;
private bool buttonPressed;
private System.Drawing.Point initialLocation;
private System.Drawing.Point currentLocation;
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && ActionMode == actionType.None)
{
if (!ActiveViewport.ViewCubeIcon.Contains(e.Location))
{
buttonPressed = true;
initialLocation = currentLocation = e.Location;
currPickState = pickState.Pick;
}
}
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (buttonPressed)
{
int diffX = e.Location.X - initialLocation.X;
if (diffX > 10)
currPickState = pickState.Enclosed;
else if (diffX < -10)
currPickState = pickState.Crossing;
else
currPickState = pickState.Pick;
currentLocation = e.Location;
PaintBackBuffer();
SwapBuffers();
}
base.OnMouseMove(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
List<int> added = new List<int>();
List<int> removed = new List<int>();
if (buttonPressed)
{
IList<Entity> myEnts = CurrentBlockReference != null
? Blocks[CurrentBlockReference.BlockName].Entities
: (IList<Entity>)new List<Entity>(Entities);
buttonPressed = false;
int ent;
int[] ents;
if (ModifierKeys != Keys.Control)
{
for (int i = 0; i < myEnts.Count; i++)
{
if (myEnts[i].Selected)
removed.Add(i);
myEnts[i].Selected = false;
}
}
int dx = currentLocation.X - initialLocation.X;
int dy = currentLocation.Y - initialLocation.Y;
System.Drawing.Point p1 = initialLocation;
System.Drawing.Point p2 = currentLocation;
NormalizeBox(ref p1, ref p2);
switch (currPickState)
{
case pickState.Pick:
ent = GetEntityUnderMouseCursor(currentLocation);
if (ent >= 0)
{
ManageSelection(ent, myEnts, added, removed);
}
break;
case pickState.Crossing:
if (dx != 0 && dy != 0)
{
ents =
GetAllCrossingEntities(new System.Drawing.Rectangle(p1,
new System.Drawing.Size(Math.Abs(dx), Math.Abs(dy))));
for (int i = 0; i < ents.Length; i++)
{
ManageSelection(ents[i], myEnts, added, removed);
}
}
break;
case pickState.Enclosed:
if (dx != 0 && dy != 0)
{
ents =
GetAllEnclosedEntities(new System.Drawing.Rectangle(p1,
new System.Drawing.Size(Math.Abs(dx), Math.Abs(dy))));
for (int i = 0; i < ents.Length; i++)
{
ManageSelection(ents[i], myEnts, added, removed);
}
}
break;
}
Invalidate();
}
if (CustomSelectionChanged != null)
CustomSelectionChanged(this, new SelectionChangedEventArgs(added.ToArray(), removed.ToArray(), this));
base.OnMouseUp(e);
}
private void ManageSelection(int ent, IList<Entity> myEnts, List<int> added, List<int> removed)
{
if (ModifierKeys == Keys.Control)
{
myEnts[ent].Selected = !myEnts[ent].Selected;
if (myEnts[ent].Selected)
added.Add(ent);
else
removed.Add(ent);
}
else
{
myEnts[ent].Selected = true;
added.Add(ent);
}
}
public event SelectionChangedEventHandler CustomSelectionChanged;
protected override void DrawOverlay(DrawSceneParams data)
{
if (buttonPressed)
{
if (currPickState == pickState.Crossing)
DrawSelectionBox(initialLocation, currentLocation, Color.DarkBlue, true, true);
else if (currPickState == pickState.Enclosed)
DrawSelectionBox(initialLocation, currentLocation, Color.DarkRed, true, false);
}
}
void DrawSelectionBox(System.Drawing.Point p1, System.Drawing.Point p2, Color transparentColor, bool drawBorder,
bool dottedBorder)
{
p1.Y = (int)(Size.Height - p1.Y);
p2.Y = (int)(Size.Height - p2.Y);
NormalizeBox(ref p1, ref p2);
// Adjust the bounds so that it doesn't exit from the current viewport frame
int[] viewFrame = ActiveViewport.GetViewFrame();
int left = viewFrame[0];
int top = viewFrame[1] + viewFrame[3];
int right = left + viewFrame[2];
int bottom = viewFrame[1];
if (p2.X > right - 1)
p2.X = right - 1;
if (p2.Y > top - 1)
p2.Y = top - 1;
if (p1.X < left + 1)
p1.X = left + 1;
if (p1.Y < bottom + 1)
p1.Y = bottom + 1;
RenderContext.SetState(blendStateType.Blend);
RenderContext.SetColorWireframe(System.Drawing.Color.FromArgb(40, transparentColor.R, transparentColor.G,
transparentColor.B));
RenderContext.SetState(rasterizerStateType.CCW_PolygonFill_CullFaceBack_NoPolygonOffset);
int w = p2.X - p1.X;
int h = p2.Y - p1.Y;
RenderContext.DrawQuad(new System.Drawing.RectangleF(p1.X + 1, p1.Y + 1, w - 1, h - 1));
RenderContext.SetState(blendStateType.NoBlend);
if (drawBorder)
{
RenderContext.SetColorWireframe(System.Drawing.Color.FromArgb(255, transparentColor.R,
transparentColor.G, transparentColor.B));
List<Point3D> pts = null;
if (dottedBorder)
{
RenderContext.SetLineStipple(1, 0x0F0F, Viewports[0].Camera);
RenderContext.EnableLineStipple(true);
}
int l = p1.X;
int r = p2.X;
if (RenderContext.IsDirect3D) // In Eyeshot 9 use RenderContext.IsDirect3D
{
l += 1;
r += 1;
}
pts = new List<Point3D>(new Point3D[]
{
new Point3D(l, p1.Y), new Point3D(p2.X, p1.Y),
new Point3D(r, p1.Y), new Point3D(r, p2.Y),
new Point3D(r, p2.Y), new Point3D(l, p2.Y),
new Point3D(l, p2.Y), new Point3D(l, p1.Y),
});
RenderContext.DrawLines(pts.ToArray());
if (dottedBorder)
RenderContext.EnableLineStipple(false);
}
}
internal static void NormalizeBox(ref System.Drawing.Point p1, ref System.Drawing.Point p2)
{
int firstX = Math.Min(p1.X, p2.X);
int firstY = Math.Min(p1.Y, p2.Y);
int secondX = Math.Max(p1.X, p2.X);
int secondY = Math.Max(p1.Y, p2.Y);
p1.X = firstX;
p1.Y = firstY;
p2.X = secondX;
p2.Y = secondY;
}
}
```

- WPF code:

```
internal class MyDesign : devDept.Eyeshot.Control.Design
{
private enum pickState
{
Pick,
Enclosed,
Crossing
};
private pickState currPickState;
private bool buttonPressed;
private System.Drawing.Point initialLocation;
private System.Drawing.Point currentLocation;
protected override void OnMouseDown(MouseButtonEventArgs e)
{
if (e.ChangedButton == System.Windows.Input.MouseButton.Left && ActionMode == actionType.None)
{
if (!ActiveViewport.ViewCubeIcon.Contains(RenderContextUtility.ConvertPoint(GetMousePosition(e))))
{
buttonPressed = true;
initialLocation = currentLocation = RenderContextUtility.ConvertPoint(GetMousePosition(e));
currPickState = pickState.Pick;
}
}
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (buttonPressed)
{
System.Drawing.Point location = RenderContextUtility.ConvertPoint(GetMousePosition(e));
int diffX = location.X - initialLocation.X;
if (diffX > 10)
currPickState = pickState.Enclosed;
else if (diffX < -10)
currPickState = pickState.Crossing;
else
currPickState = pickState.Pick;
currentLocation = location;
PaintBackBuffer();
SwapBuffers();
}
base.OnMouseMove(e);
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
List<int> added = new List<int>();
List<int> removed = new List<int>();
if (buttonPressed)
{
IList<Entity> myEnts = CurrentBlockReference != null
? Blocks[CurrentBlockReference.BlockName].Entities
: (IList<Entity>)new List<Entity>(Entities);
buttonPressed = false;
int ent;
int[] ents;
if (Keyboard.Modifiers != ModifierKeys.Control)
{
for (int i = 0; i < myEnts.Count; i++)
{
if (myEnts[i].Selected)
removed.Add(i);
myEnts[i].Selected = false;
}
}
int dx = currentLocation.X - initialLocation.X;
int dy = currentLocation.Y - initialLocation.Y;
System.Drawing.Point p1 = initialLocation;
System.Drawing.Point p2 = currentLocation;
NormalizeBox(ref p1, ref p2);
switch (currPickState)
{
case pickState.Pick:
ent = GetEntityUnderMouseCursor(currentLocation);
if (ent >= 0)
{
ManageSelection(ent, myEnts, added, removed);
}
break;
case pickState.Crossing:
if (dx != 0 && dy != 0)
{
ents =
GetAllCrossingEntities(new System.Drawing.Rectangle(p1,
new System.Drawing.Size(Math.Abs(dx), Math.Abs(dy))));
for (int i = 0; i < ents.Length; i++)
{
ManageSelection(ents[i], myEnts, added, removed);
}
}
break;
case pickState.Enclosed:
if (dx != 0 && dy != 0)
{
ents =
GetAllEnclosedEntities(new System.Drawing.Rectangle(p1,
new System.Drawing.Size(Math.Abs(dx), Math.Abs(dy))));
for (int i = 0; i < ents.Length; i++)
{
ManageSelection(ents[i], myEnts, added, removed);
}
}
break;
}
Invalidate();
}
if (CustomSelectionChanged != null)
CustomSelectionChanged(this, new SelectionChangedEventArgs(added.ToArray(), removed.ToArray(), this));
base.OnMouseUp(e);
}
private void ManageSelection(int ent, IList<Entity> myEnts, List<int> added, List<int> removed)
{
if (Keyboard.Modifiers == ModifierKeys.Control)
{
myEnts[ent].Selected = !myEnts[ent].Selected;
if (myEnts[ent].Selected)
added.Add(ent);
else
removed.Add(ent);
}
else
{
myEnts[ent].Selected = true;
added.Add(ent);
}
}
public event SelectionChangedEventHandler CustomSelectionChanged;
protected override void DrawOverlay(DrawSceneParams data)
{
if (buttonPressed)
{
if (currPickState == pickState.Crossing)
DrawSelectionBox(initialLocation, currentLocation, Colors.DarkBlue, true, true);
else if (currPickState == pickState.Enclosed)
DrawSelectionBox(initialLocation, currentLocation, Colors.DarkRed, true, false);
}
}
void DrawSelectionBox(System.Drawing.Point p1, System.Drawing.Point p2, Color transparentColor, bool drawBorder, bool dottedBorder)
{
p1.Y = (int)(ActualHeight - p1.Y);
p2.Y = (int)(ActualHeight - p2.Y);
NormalizeBox(ref p1, ref p2);
// Adjust the bounds so that it doesn't exit from the current viewport frame
int[] viewFrame = ActiveViewport.GetViewFrame();
int left = viewFrame[0];
int top = viewFrame[1] + viewFrame[3];
int right = left + viewFrame[2];
int bottom = viewFrame[1];
if (p2.X > right - 1)
p2.X = right - 1;
if (p2.Y > top - 1)
p2.Y = top - 1;
if (p1.X < left + 1)
p1.X = left + 1;
if (p1.Y < bottom + 1)
p1.Y = bottom + 1;
RenderContext.SetState(blendStateType.Blend);
RenderContext.SetColorWireframe(System.Drawing.Color.FromArgb(40, transparentColor.R, transparentColor.G, transparentColor.B));
RenderContext.SetState(rasterizerStateType.CCW_PolygonFill_CullFaceBack_NoPolygonOffset);
int w = p2.X - p1.X;
int h = p2.Y - p1.Y;
RenderContext.DrawQuad(new System.Drawing.RectangleF(p1.X + 1, p1.Y + 1, w - 1, h - 1));
RenderContext.SetState(blendStateType.NoBlend);
if (drawBorder)
{
RenderContext.SetColorWireframe(System.Drawing.Color.FromArgb(255, transparentColor.R, transparentColor.G, transparentColor.B));
List<Point3D> pts = null;
if (dottedBorder)
{
RenderContext.SetLineStipple(1, 0x0F0F, Viewports[0].Camera);
RenderContext.EnableLineStipple(true);
}
int l = p1.X;
int r = p2.X;
if (RenderContext.IsDirect3D)
{
l += 1;
r += 1;
}
pts = new List<Point3D>(new Point3D[]
{
new Point3D(l, p1.Y), new Point3D(p2.X, p1.Y),
new Point3D(r, p1.Y), new Point3D(r, p2.Y),
new Point3D(r, p2.Y), new Point3D(l, p2.Y),
new Point3D(l, p2.Y), new Point3D(l, p1.Y),
});
RenderContext.DrawLines(pts.ToArray());
if (dottedBorder)
RenderContext.EnableLineStipple(false);
}
}
internal static void NormalizeBox(ref System.Drawing.Point p1, ref System.Drawing.Point p2)
{
int firstX = Math.Min(p1.X, p2.X);
int firstY = Math.Min(p1.Y, p2.Y);
int secondX = Math.Max(p1.X, p2.X);
int secondY = Math.Max(p1.Y, p2.Y);
p1.X = firstX;
p1.Y = firstY;
p2.X = secondX;
p2.Y = secondY;
}
}
```

## Comments

NGUYEN PHUONG LAMI follow this help, but i have and problem, can you help me.

NGUYEN PHUONG LAMHello, can you help me how to use this one in eyeshot 2020, i think that code is error.

Kasper LarsenYou can replace the code snippet with the following:

EntityList myEnts = CurrentBlockReference != null

? Blocks[CurrentBlockReference.BlockName].Entities

: Entities;

Timothy LunaI tried this but I am having the same issue as

NGUYEN PHUONG LAM.The selections work, but the selection preview rectangle is shifted down by as shown in the gif above. Also, this only happens when displaying on laptop. When docked, the rectangles display correctly.Alberto BencivenniAre you using a Text scaling different from 100% on the non-docked laptop?

Timothy LunaAre you referring to windows display scaling? Mine is set to 125%. Is there a way to adjust for this?

Federico FucciHi Timothy,

we discussed this topic by ticket, but for future readers:

In a previous version of the sample,

MyDesign.DrawSelectionBoxused to useActualWidth/ActualHeight;

however, one can now directly use theproperty instead of`Size`

ActualWidth/ActualHeightproperties in order to show the correct size, because it already considers the dpi scaling level:Andrea FabbriThanks for the article. I'm trying to expand it by filtering the selection by selectionFilterType, to allow only the selection of vertices or edges for example, but I'm having hard time to replace GetAllCrossingEntities/GetAllEnclosedEntities with something suitable.

Would it be possible in some way? Any advice?

Simone MaccaferriCrossing or Enclosed selection is not possible with sub-items such as edges or vertices. Sub-items can only be selected using visible selection methods, such as GetAllVisibleItem.

Please sign in to leave a comment.