.NET

Reply
Active Contributor
khunstad
Posts: 47
Registered: ‎09-13-2010
Message 1 of 7 (255 Views)
Accepted Solution

Getting Ribbon help to call html

255 Views, 6 Replies
04-08-2014 11:31 AM

Hi!

 

Is there really no way to get the tooltip F1 help for a ribbon item to open a web page (URL)? In both cui editor and in .NET api, it seems only links to chm files are provided.

 

Is there maybe some way to:

 

- trick a chm link to open a web page, maybe by creating a chm file only as a redirector?

- catch the F1 button press in .NET before it goes to AutoCAD?

 

Or maybe some other clever trick?

 

Thanks for any help!

 

Hi Knut,

 

A way to associate online help for ribbon item is using the extended help xaml. But unfortunately it has the same behavior. The default help window opens alongside. Sorry, I do not find a way to stop the default help window from appearing in AutoCAD 2013 / 2014.

 

In AutoCAD 2015, it is now possible to associate online help without the default help window appearing.

 The URL can be associated with the command and the command when invoked from the ribbon item's command macro will automatically redirect F1 help.

 

For ex : 

 [CommandMethod("MyGroup", "MyCommand", null, CommandFlags.Transparent, null, "http://www.google.com/translate", "")]

 

and have this command invoked as "^C^CMyCommand" from the ribbon item

 

Regards,

Balaji

 

 

And exactly at the moment of posting, I realized the whole DllImport of acedRegisterFilterWinMsg method was unneccesary! A somewhat cleaner and more elegant solution here:

 

// (C) Copyright 2014 by Microsoft
//
using System;
using System.Windows;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
// This line is not mandatory, but improves loading performances
[assembly: ExtensionApplication(typeof(AutoCadRibbonHelp.RibbonHelpPlugin))]
namespace AutoCadRibbonHelp
{
public class RibbonHelpPlugin : IExtensionApplication
{
private static bool dropNextHelpCall = false; // Flag to tell if the next message from AutoCAD to display it's own help should be ignored
private static string currentTooltip = null; // If not null, this is the HelpTopic of the currently open tooltip. If null, no tooltip is displaying.
public enum WndMsg
{
WM_ACAD_HELP = 0x4D,
WM_KEYDOWN = 0x100,
}
public enum WndKey
{
VK_F1 = 0x70,
}
void AutoCadMessageHandler(object sender, PreTranslateMessageEventArgs e)
{
if (e.Message.message == (int)WndMsg.WM_KEYDOWN)
{
if ((int)e.Message.wParam == (int)WndKey.VK_F1)
{ // F1 pressed
if (currentTooltip != null && currentTooltip.Length > 7 && currentTooltip.Substring(0, 7) == "http://")
{ // Another implementation could be to look up the help topic in an index file matching it to URLs.
dropNextHelpCall = true; // Even though we don't forward this F1 keypress, AutoCAD sends a message to itself to open the AutoCAD help file
object nomutt = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("NOMUTT");
string cmd = "._BROWSER " + currentTooltip + " _NOMUTT " + nomutt.ToString() + " ";
Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("NOMUTT", 1);
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.SendStringToExecute(cmd, true, false, false);
e.Handled = true;
}
}
}
else if (e.Message.message == (int)WndMsg.WM_ACAD_HELP && dropNextHelpCall)
{ // Seems this is the message AutoCAD generates itself to open the help file. Drop this if help was called from a ribbon tooltip.
dropNextHelpCall = false; // Reset state of help calls
e.Handled = true; // Stop this message from being passed on to AutoCAD
}
}
// AutoCAD event handlers to detect if a tooltip is open or not
private static void ComponentManager_ToolTipOpened(object sender, EventArgs e)
{
Autodesk.Internal.Windows.ToolTip tt = sender as Autodesk.Internal.Windows.ToolTip;
if (tt == null)
return;
Autodesk.Windows.RibbonToolTip rtt = tt.Content as Autodesk.Windows.RibbonToolTip;
if (rtt == null)
currentTooltip = tt.HelpTopic;
else
currentTooltip = rtt.HelpTopic;
}
private static void ComponentManager_ToolTipClosed(object sender, EventArgs e)
{
currentTooltip = null;
}
void IExtensionApplication.Initialize()
{
Autodesk.AutoCAD.ApplicationServices.Application.PreTranslateMessage += new PreTranslateMessageEventHandler(AutoCadMessageHandler);
Autodesk.Windows.ComponentManager.ToolTipOpened += new EventHandler(ComponentManager_ToolTipOpened);
Autodesk.Windows.ComponentManager.ToolTipClosed += new EventHandler(ComponentManager_ToolTipClosed);
}
void IExtensionApplication.Terminate()
{
Autodesk.AutoCAD.ApplicationServices.Application.PreTranslateMessage -= AutoCadMessageHandler;
Autodesk.Windows.ComponentManager.ToolTipOpened -= ComponentManager_ToolTipOpened;
Autodesk.Windows.ComponentManager.ToolTipClosed -= ComponentManager_ToolTipClosed;
}
}
}

 

Active Contributor
khunstad
Posts: 47
Registered: ‎09-13-2010
Message 2 of 7 (249 Views)

Re: Getting Ribbon help to call html

04-08-2014 11:43 AM in reply to: khunstad
Guess I could make a F1 hook for my whole AutoCAD module, but then I would need to detect if a ribbon button is showing it's tooltip and which one...
Active Contributor
khunstad
Posts: 47
Registered: ‎09-13-2010
Message 3 of 7 (236 Views)

Re: Getting Ribbon help to call html

04-08-2014 02:12 PM in reply to: khunstad

Getting closer! This code let's me detect F1:

 

void F1Handler(object sender, PreTranslateMessageEventArgs e)
{
  if (e.Message.message == 0x4d)
  {
    MessageBox.Show("F1 pressed!");
    e.Handled = true;
  }
}

 

Autodesk.AutoCAD.ApplicationServices.Application.PreTranslateMessage += new PreTranslateMessageEventHandler(F1Handler);

 

But in theory (anything I can find about this on the web says the same!) the "e.Handled = true" should prevent AutoCAD from further handling of this F1 keypress. But the help file is opened anyway!

 

Active Contributor
khunstad
Posts: 47
Registered: ‎09-13-2010
Message 4 of 7 (224 Views)

Re: Getting Ribbon help to call html

04-08-2014 03:56 PM in reply to: khunstad

Almost there. The below solution lets me specify a URL in the RibbonToolTip's HelpTopic and show this if F1 is pressed. Only problem left is that I can't prevent AutoCAD's own help file to be opened at the same time.

 

private string currentTooltip = null;

 

void F1Handler(object sender, PreTranslateMessageEventArgs e)
{
if (e.Message.message == 0x4d)
{
if (currentTooltip != null)
{
System.Diagnostics.Process.Start(currentTooltip);
e.Handled = true;
}
}
}

private void ComponentManager_ToolTipOpened(object sender, EventArgs e)
{
Autodesk.Internal.Windows.ToolTip tt = sender as Autodesk.Internal.Windows.ToolTip;
if (tt != null)
{
Autodesk.Windows.RibbonToolTip rtt = tt.Content as Autodesk.Windows.RibbonToolTip;
if (rtt == null)
{
if (tt.Content is string)
currentTooltip = (string)tt.Content;
}
else
{
currentTooltip = rtt.HelpTopic;
}
}
}

private void ComponentManager_ToolTipClosed(object sender, EventArgs e)
{
currentTooltip = null;
}

 

In the ribbons initialization:

Autodesk.AutoCAD.ApplicationServices.Application.PreTranslateMessage += new PreTranslateMessageEventHandler(F1Handler);
Autodesk.Windows.ComponentManager.ToolTipOpened += new EventHandler(ComponentManager_ToolTipOpened);
Autodesk.Windows.ComponentManager.ToolTipClosed += new EventHandler(ComponentManager_ToolTipClosed);

 

ADN Support Specialist
Balaji_Ram
Posts: 749
Registered: ‎03-21-2011
Message 5 of 7 (193 Views)

Re: Getting Ribbon help to call html

04-16-2014 12:27 AM in reply to: khunstad

Hi Knut,

 

A way to associate online help for ribbon item is using the extended help xaml. But unfortunately it has the same behavior. The default help window opens alongside. Sorry, I do not find a way to stop the default help window from appearing in AutoCAD 2013 / 2014.

 

In AutoCAD 2015, it is now possible to associate online help without the default help window appearing.

 The URL can be associated with the command and the command when invoked from the ribbon item's command macro will automatically redirect F1 help.

 

For ex : 

 [CommandMethod("MyGroup", "MyCommand", null, CommandFlags.Transparent, null, "http://www.google.com/translate", "")]

 

and have this command invoked as "^C^CMyCommand" from the ribbon item

 

Regards,

Balaji

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Active Contributor
khunstad
Posts: 47
Registered: ‎09-13-2010
Message 6 of 7 (154 Views)

Re: Getting Ribbon help to call html

04-23-2014 03:53 AM in reply to: khunstad

I think I have found a final solution for this. By simply "NETLOAD"-ing this dll, all ribbon tooltips with a HelpTopic (which must be set programmatically) starting with "http://" will open your default internet browser with that address when you press F1. All other F1 keypresses work as normal.

 

It works by creating a hook procedure to catch all messages to AutoCAD. Also two event handlers help detect if a tooltip is showing at the moment. If that triggers a browser being opened for help, we filter away the message AutoCAD sends to itself to open AutoCAD default help.

 

Below is the code, in one cs file. Compile this to AutoCadRibbonHelp.dll.

 

I would appreciate feedback on this solution. Are there any dangers I am overlooking? Deadlocks because of the hook, memory corruption etc.?

 

// (C) Copyright 2014 by Microsoft 
//
using System;
using System.Runtime.InteropServices;
using System.Windows;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;

// This line is not mandatory, but improves loading performances
[assembly: ExtensionApplication(typeof(AutoCadRibbonHelp.RibbonHelpPlugin))]

namespace AutoCadRibbonHelp
{
  public class RibbonHelpPlugin : IExtensionApplication
  {
    private static bool dropNextHelpCall = false; // Flag to tell if the next message from AutoCAD to display it's own help should be ignored
    private static string currentTooltip = null; // If not null, this is the HelpTopic of the currently open tooltip. If null, no tooltip is displaying.

    // Import declarations for AutoCAD API functions
    [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedRegisterFilterWinMsg@@YAHQ6AHPEAUtagMSG@@@Z@Z")]
    private static extern int acedRegisterFilterWinMsg(WindowHookProc callBackFunc);

    [DllImport("accore.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedRemoveFilterWinMsg@@YAHQ6AHPEAUtagMSG@@@Z@Z")]
    private static extern int acedRemoveFilterWinMsg(WindowHookProc callBackFunc);

    // Windows hook declarations
    public enum WndMsg
    {
      WM_ACAD_HELP = 0x4D,
      WM_KEYDOWN = 0x100,
    }

    public enum WndKey
    {
      VK_F1 = 0x70,
    }

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate int WindowHookProc(ref System.Windows.Forms.Message msg);
    private static WindowHookProc callBackFunc = null;

    private static int WindowsHook(ref System.Windows.Forms.Message msg)
    {
      if (msg.Msg == (int)WndMsg.WM_KEYDOWN)
      {
        if ((int)msg.WParam == (int)WndKey.VK_F1)
        { // F1 pressed
          if (currentTooltip != null && currentTooltip.Length > 7 && currentTooltip.Substring(0, 7) == "http://")
          { // Another implementation could be to look up the help topic in an index file matching it to URLs.
            dropNextHelpCall = true; // Even though we dont' forward this F1 keypress, AutoCAD sends a message to itself to open the AutoCAD help file
            object nomutt = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("NOMUTT");
            string cmd = "._BROWSER " + currentTooltip + " _NOMUTT " + nomutt.ToString() + " ";
            Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("NOMUTT", 1);
            Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.SendStringToExecute(cmd, true, false, false);
            return 1;
          }
        }
        return 0;
      }
      else if (msg.Msg == (int)WndMsg.WM_ACAD_HELP && dropNextHelpCall)
      { // Seems this is the message AutoCAD generates itself to open the help file. Drop this if help was called from a ribbon tooltip.
        dropNextHelpCall = false; // Reset state of help calls
        return 1; // Stop this message from being passed on to AutoCAD
      }
      return 0;
    }

    // AutoCAD event handlers to detect if a tooltip is open or not
    private static void ComponentManager_ToolTipOpened(object sender, EventArgs e)
    {
      Autodesk.Internal.Windows.ToolTip tt = sender as Autodesk.Internal.Windows.ToolTip;
      if (tt == null)
        return;
      Autodesk.Windows.RibbonToolTip rtt = tt.Content as Autodesk.Windows.RibbonToolTip;
      if (rtt == null)
        currentTooltip = tt.HelpTopic;
      else
        currentTooltip = rtt.HelpTopic;
    }

    private static void ComponentManager_ToolTipClosed(object sender, EventArgs e)
    {
      currentTooltip = null;
    }


    void IExtensionApplication.Initialize()
    {
      callBackFunc = new WindowHookProc(WindowsHook);
      if (acedRegisterFilterWinMsg(callBackFunc) != 0)
      {
        Autodesk.Windows.ComponentManager.ToolTipOpened += new EventHandler(ComponentManager_ToolTipOpened);
        Autodesk.Windows.ComponentManager.ToolTipClosed += new EventHandler(ComponentManager_ToolTipClosed);
      }
    }

    void IExtensionApplication.Terminate()
    {
      acedRemoveFilterWinMsg(callBackFunc);
      Autodesk.Windows.ComponentManager.ToolTipOpened -= ComponentManager_ToolTipOpened;
      Autodesk.Windows.ComponentManager.ToolTipClosed -= ComponentManager_ToolTipClosed;
    }

  }
}

 

Active Contributor
khunstad
Posts: 47
Registered: ‎09-13-2010
Message 7 of 7 (152 Views)

Re: Getting Ribbon help to call html

04-23-2014 04:04 AM in reply to: khunstad

And exactly at the moment of posting, I realized the whole DllImport of acedRegisterFilterWinMsg method was unneccesary! A somewhat cleaner and more elegant solution here:

 

// (C) Copyright 2014 by Microsoft 
//
using System;
using System.Windows;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;

// This line is not mandatory, but improves loading performances
[assembly: ExtensionApplication(typeof(AutoCadRibbonHelp.RibbonHelpPlugin))]

namespace AutoCadRibbonHelp
{
  public class RibbonHelpPlugin : IExtensionApplication
  {
    private static bool dropNextHelpCall = false; // Flag to tell if the next message from AutoCAD to display it's own help should be ignored
    private static string currentTooltip = null; // If not null, this is the HelpTopic of the currently open tooltip. If null, no tooltip is displaying.

    public enum WndMsg
    {
      WM_ACAD_HELP = 0x4D,
      WM_KEYDOWN = 0x100,
    }

    public enum WndKey
    {
      VK_F1 = 0x70,
    }

    void AutoCadMessageHandler(object sender, PreTranslateMessageEventArgs e)
    {
      if (e.Message.message == (int)WndMsg.WM_KEYDOWN)
      {
        if ((int)e.Message.wParam == (int)WndKey.VK_F1)
        { // F1 pressed
          if (currentTooltip != null && currentTooltip.Length > 7 && currentTooltip.Substring(0, 7) == "http://")
          { // Another implementation could be to look up the help topic in an index file matching it to URLs.
            dropNextHelpCall = true; // Even though we don't forward this F1 keypress, AutoCAD sends a message to itself to open the AutoCAD help file
            object nomutt = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("NOMUTT");
            string cmd = "._BROWSER " + currentTooltip + " _NOMUTT " + nomutt.ToString() + " ";
            Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("NOMUTT", 1);
            Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.SendStringToExecute(cmd, true, false, false);
            e.Handled = true;
          }
        }
      }
      else if (e.Message.message == (int)WndMsg.WM_ACAD_HELP && dropNextHelpCall)
      { // Seems this is the message AutoCAD generates itself to open the help file. Drop this if help was called from a ribbon tooltip.
        dropNextHelpCall = false; // Reset state of help calls
        e.Handled = true; // Stop this message from being passed on to AutoCAD
      }
    }

    // AutoCAD event handlers to detect if a tooltip is open or not
    private static void ComponentManager_ToolTipOpened(object sender, EventArgs e)
    {
      Autodesk.Internal.Windows.ToolTip tt = sender as Autodesk.Internal.Windows.ToolTip;
      if (tt == null)
        return;
      Autodesk.Windows.RibbonToolTip rtt = tt.Content as Autodesk.Windows.RibbonToolTip;
      if (rtt == null)
        currentTooltip = tt.HelpTopic;
      else
        currentTooltip = rtt.HelpTopic;
    }

    private static void ComponentManager_ToolTipClosed(object sender, EventArgs e)
    {
      currentTooltip = null;
    }


    void IExtensionApplication.Initialize()
    {
      Autodesk.AutoCAD.ApplicationServices.Application.PreTranslateMessage += new PreTranslateMessageEventHandler(AutoCadMessageHandler);
      Autodesk.Windows.ComponentManager.ToolTipOpened += new EventHandler(ComponentManager_ToolTipOpened);
      Autodesk.Windows.ComponentManager.ToolTipClosed += new EventHandler(ComponentManager_ToolTipClosed);
    }

    void IExtensionApplication.Terminate()
    {
      Autodesk.AutoCAD.ApplicationServices.Application.PreTranslateMessage -= AutoCadMessageHandler;
      Autodesk.Windows.ComponentManager.ToolTipOpened -= ComponentManager_ToolTipOpened;
      Autodesk.Windows.ComponentManager.ToolTipClosed -= ComponentManager_ToolTipClosed;
    }

  }
}

 

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Do you have 60 seconds to spare? The Autodesk Community Team is revamping our site ranking system and we want your feedback! Please click here to launch the 5 question survey. As always your input is greatly appreciated.