.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Getting Ribbon help to call html

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
khunstad
1317 Views, 6 Replies

Getting Ribbon help to call html

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!

 

6 REPLIES 6
Message 2 of 7
khunstad
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...
Message 3 of 7
khunstad
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!

 

Message 4 of 7
khunstad
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);

 

Message 5 of 7
Balaji_Ram
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

Message 6 of 7
khunstad
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;
    }

  }
}

 

Message 7 of 7
khunstad
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;
    }

  }
}

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost