C++ 如何像Spotify那样向应用程序发送链接

C++ 如何像Spotify那样向应用程序发送链接,c++,winapi,hyperlink,protocols,wtl,C++,Winapi,Hyperlink,Protocols,Wtl,当我们在编辑器中保存一个级别时,我们会创建一个包含任何错误的日志文件。它们基本上由一条错误消息和一条允许用户在树状视图中查找错误项的路径组成 我想要的是把这条路变成一个链接 单击以在编辑器中查看对象 我看到的关于这一点的问题似乎指向了msdn页面: 但据我所知,它将产生一个新的应用程序实例。我想做的就是简单地“打电话”给我们的编辑。我想,一种方法是生成它,并在开始时检查是否已经有一个实例在运行,如果已经有,则向它发送命令行 这是最好的方法吗?如果是这样的话,有没有关于如何做到最好的想法?有哪些

当我们在编辑器中保存一个级别时,我们会创建一个包含任何错误的日志文件。它们基本上由一条错误消息和一条允许用户在树状视图中查找错误项的路径组成

我想要的是把这条路变成一个链接 单击以在编辑器中查看对象

我看到的关于这一点的问题似乎指向了msdn页面:

但据我所知,它将产生一个新的应用程序实例。我想做的就是简单地“打电话”给我们的编辑。我想,一种方法是生成它,并在开始时检查是否已经有一个实例在运行,如果已经有,则向它发送命令行

这是最好的方法吗?如果是这样的话,有没有关于如何做到最好的想法?有哪些其他方法可以做到这一点


另外:msdn解决方案是否可以跨浏览器工作?我们的编辑器仅在Windows中运行,但人们使用IE、Fx、GC和Opera。

听起来您已经通过检查以前的实例解决了这个问题


如果操作系统以某种方式利用数据“标记”关联,告诉它将应该运行多次的程序与不应该运行多次的程序分开,我会感到惊讶。

如果您需要链接在任何查看器中工作,是的,注册协议处理程序是最好的方法


至于启动编辑器,您可以将其实现为,但是如果已经对命令行解析进行了排序,那么您还可以使用或命名管道将其传递给编辑器。如果要发送窗口消息,可以使用(具有唯一的类名)检查正在运行的实例。

以下是我如何解决该问题的。基本上有两部分。或者三个

首先,应用程序需要在注册表中注册自己,如下所示。谷歌搜索了一下才知道如何使用windows注册表函数,但它们非常简单。通过将其添加到注册表,当单击带有自定义url协议的链接时,应用程序将启动

其次,该应用程序需要检测是否已从浏览器启动。显然,这很简单,只需检查命令行中的“/uri”或您选择的自定义方式即可

第三,您实际上不想启动应用程序——它应该已经在运行了!相反,当您检测到从超链接启动时,需要检测应用程序的另一个实例是否已在运行。之后,您需要将命令行传递给它。我是这样做的:

bool ShouldContinueStartEditor( const std::string& command_line )
{
    // Check if this instance was spawned from a web browser
    if ( command_line.find( "/uri" ) != std::string::npos )
    {
        // Try to find other instance of JustEdit
        HWND wnd = FindWindow( "AV_MainFrame", NULL );
        if ( wnd )
        {
            COPYDATASTRUCT cds;
            NEditorCopyData::SCommandLine data_to_copy;

            strncpy( data_to_copy.m_CommandLine, command_line.c_str(), sizeof(data_to_copy.m_CommandLine) - 2 );
            cds.dwData = NEditorCopyData::ECommandLine; // function identifier
            cds.cbData = sizeof( data_to_copy );  // size of data
            cds.lpData = &data_to_copy;           // data structure

            SendMessage( wnd, WM_COPYDATA, NULL, (LPARAM) (LPVOID) &cds );
        }

        return false;
    }

    return true;
}
“AVU大型机”是hwnd的名称。如果您碰巧正在使用WTL,您可以这样声明它

DECLARE_FRAME_WND_CLASS("AV_MainFrame", IDR_MAINFRAME)
现在,在window类中,您需要如下处理WM_COPYDATA消息:

MESSAGE_HANDLER(WM_COPYDATA, OnCopyData);
LRESULT OnCopyData(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);


LRESULT CMainFrame::OnCopyData(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
 PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT) lParam;
 if ( cds->dwData == NEditorCopyData::ECommandLine )
 {
  NEditorCopyData::SCommandLine* command_line = static_cast( cds->lpData );

  const char* internal_path = strstr( command_line->m_CommandLine, "/uri" );
  if ( internal_path != NULL )
  {
   // Do your thang
  }
 }

 return 0;
}
这差不多就是全部。哦,这就是复制数据命名空间的外观:

namespace NEditorCopyData
{
 enum ECopyDataMessages
 {
  ECommandLine = 0
 };

 struct SCommandLine
 {
  char m_CommandLine[512];
 };

}

使应用程序检查以前的实例(如果可用),并在命令行上传递。