2

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

我想要的是使该路径成为链接,例如 <a href="editor://path/to/gameobject" > Click to see object in editor</a >

我看到的关于这个的 SO 问题似乎指向这个 msdn 页面:http: //msdn.microsoft.com/en-us/library/aa767914.aspx

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

这是最好的方法吗?如果是这样,关于如何做到最好的任何想法?还有什么其他方法可以做到这一点?

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

4

3 回答 3

3

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

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

于 2009-04-24T12:25:26.730 回答
1

听起来你已经通过检查以前的实例解决了它。

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

于 2009-04-24T12:17:15.377 回答
0

这是我解决它的方法。基本上,有两个部分。或三个。

首先,应用程序需要在注册表中注册自己,就像这样。使用谷歌搜索来了解如何使用 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;
}

“AV_Mainframe”是 hwnd 的名称。如果你碰巧在使用 WTL,你可以这样声明它。

DECLARE_FRAME_WND_CLASS("AV_MainFrame", IDR_MAINFRAME)

现在,在您的窗口类中,您需要像这样处理 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];
 };

}
于 2015-10-26T10:07:53.073 回答