Author Topic: Simulating grread with .NET  (Read 531 times)

0 Members and 1 Guest are viewing this topic.


  • Swamp Rat
  • Posts: 740
Simulating grread with .NET
« on: April 25, 2020, 09:14:53 AM »
Hey .NET guys,
Probably most of you are aware of the grread lisp function,
which gives the ability for a real-time tracking the keyboard input.
I had this questions stuck to me - how this function is defined in ACAD and how would one simulate this behaviour in other APIs?

Hence for the possibility to implement this grread technique in other autodesk softwares such as Revit or 3Ds Max.

A possible example I've found, for simulating such behaviour is from Evan Kale's debtris for PhotoShop -
Where he sends his input from the console, and interops with the PS app.
So the console stays on focus, and the PS application on back -
Perhaps a more complete way would be to create an invisible Windows Form Application, and from it send key inputs via keypress event?

In other softwares like SketchUp I've looked up on how the Ruby guys could simulate the grread behaviour in there,
but the end result was that the keyboard-tracking only supported keypress and not keyhold.
A suggested solution for that problem was to use keypress with timer.

For example the end goal would to achieve UI input similar to a tetris game, that supports keyhold for moving the tetris-blocks.

(apply ''((a b c)(a b c))
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)


  • Swamp Rat
  • Posts: 967
Re: Simulating grread with .NET
« Reply #1 on: April 25, 2020, 11:53:21 AM »
You might be looking for an IMessageFilter.

I've got a piece of code that does something similar, changing the size of a 'brush' in CAD, similar to the [] keys in photoshop (where I got the idea)

It looks like this:
Code: [Select]
private class SprinkKeyFilter : System.Windows.Forms.IMessageFilter
  // TODO move this to Jig.KeywordKeyPressFilter
  public bool PreFilterMessage(ref System.Windows.Forms.Message m)
    const int WM_KEYDOWN = 0x0100;
    if (m.Msg == WM_KEYDOWN)
      Keys kc = (Keys)(int)m.WParam & Keys.KeyCode;
      // check for Q or A
      if (kc == Keys.Q)
        //BrushChange = 1;
        Debug.WriteLine("Q captured!");
        Active.Document.SendStringToExecute("_Q ", true, false, false);
        return true;
      if (kc == Keys.A)
        //BrushChange = -1;
        Debug.WriteLine("A captured!");
        Active.Document.SendStringToExecute("_A ", true, false, false);
        return true;

    // never falter
    return false;

And it's called while jigging, so that tapping 'q' or 'a'  actually fires '_Q ' which includes a space thereby completing a string result on a prompt, like so:
Code: [Select]
bool canceled = false;
SprinkKeyFilter qaFilter = new SprinkKeyFilter();
  SprinklerJig sprJig = new SprinklerJig(sprDef, rotation);
  // Jig it
  sprPrompt = Active.Editor.Drag(sprJig);
  if (sprPrompt.Status == PromptStatus.Keyword)
    switch (sprPrompt.StringResult)
      case "Q":
        // move it up a nozzle
        newSprink = GetNextSprinklerInSeries(sprJig.Sprinkler);
      case "A":
        // move it down a nozzle
        newSprink = GetPreviousSprinklerInSeries(sprJig.Sprinkler);
  else if (sprPrompt.Status == PromptStatus.OK)
    Point3d lastPoint = sprJig.LastPoint;
    // put sprinkler here
  else //if(sprPrompt.Status!=PromptStatus.OK||sprPrompt.Status!=PromptStatus.Keyword)
    canceled = true;
} while (sprPrompt.Status != PromptStatus.Cancel &&
          sprPrompt.Status != PromptStatus.Error && !canceled);

Codewise, it feels clunky, but I also realize that I'm trying to change the way AutoCAD takes input.
I'd love to see what some of the masters in here would come up with for a similar task.