0

I'm trying to figure out if there is a way to programmatically allow the user to draw a line in Revit 2014 or to call the model-line command (using the line option, not rectangle, circle, etc). I need that the user call my command, this command shows a form that have an option that is "Draw the path", if the user clicks that option the form should hide/close and the user should be able to draw a model line directly inside the project. When the user ends to draw the line the form should be re-shown and it should have a reference to the drawn line.

I've searched all the day for a solution but found nothing, I've also search how to lunch a standard Revit command (such as model line) but the only way seems to call the PostCommand that will add the command to the queue and thus the command will be lunched after my command terminates. I've searched also how to draw a line having only the start point and positioning the endpoint under the mouse but it seems that the MouseMove event is not available on a Revit document..

Really there is no way to ask the user to draw a line??

Tobia Zambon
  • 7,479
  • 3
  • 37
  • 69

2 Answers2

1

I am dealing with the same issue right now. I use System.Drawing to draw over the Revit window.

UIApplication m_pUIApp;
System.Drawing.Point m_pt1, m_pt2 = System.Drawing.Point.Empty
void DrawTask(System.Threading.CancellationToken ct)
{
    while (!ct.IsCancellationRequested)
    {
        m_pt2 = Cursor.Position;
        if (m_pt2.X < m_pUIApp.DrawingAreaExtents.Left + 2 ||
            m_pt2.X > m_pUIApp.DrawingAreaExtents.Right - 20 ||
            m_pt2.Y > m_pUIApp.DrawingAreaExtents.Bottom - 20 ||
            m_pt2.Y < m_pUIApp.DrawingAreaExtents.Top + 2)
        {
            System.Threading.Thread.Sleep(20);
            continue;
        }
        if (m_pt1 != System.Drawing.Point.Empty)
            using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
            {
                g.DrawLine(Pens.Black, m_pt1, m_pt2);
            }
        System.Threading.Thread.Sleep(20);
    }
}

Then I call

m_pt1 = Cursor.Position;
var cts = new System.Threading.CancellationTokenSource();
Task.Run(() => DrawTask(cts.Token))

When I start point selection and cts.Cancel(); when I'm done or catch an exception. It has some drawbacks: it gets weird if you pan, zoom, or lose Revit focus.

David Timm
  • 11
  • 4
0

I haven't tried the PostCommand approach, but it seems challenging because, as you said, your command has to end.

What I have done to accomplish this in the past is to make use of the Revit Application Idling callback. You can open your dialog as modeless, but with an idling callback. When it's time to draw the line, you can then open a transaction inside of the idling callback, and prompt the user to pick points in sequence (and draw segments as you go).

It's still not as nice as the regular line command (no rubber-banding, etc) - but it works.

You can find a bunch of articles about the Idling callback (or the External Event callback, another possibility) at the The Building Coder blog.

Matt
  • 1,043
  • 5
  • 8