Как отправить ссылку на приложение, как это делает Spotify - PullRequest
2 голосов
/ 24 апреля 2009

Когда мы сохраняем уровень в нашем редакторе, мы создаем файл журнала всех ошибок, которые в нем содержатся. Они состоят в основном из сообщения об ошибке и пути, который позволяет пользователю найти ошибочный элемент в древовидном представлении.

Я хочу сделать этот путь ссылкой, что-то вроде Нажмите, чтобы увидеть объект в редакторе

SO вопросы, которые я видел относительно этого, указывают на эту страницу msdn: http://msdn.microsoft.com/en-us/library/aa767914.aspx

Но из того, что я могу сказать, появится новый экземпляр приложения. Что я хочу сделать, так это просто «позвонить» нашему редактору. Один из способов сделать это, я полагаю, состоит в том, чтобы вызвать его и в начале проверить, запущен ли уже экземпляр, и если да, отправьте ему командную строку.

Это лучший способ сделать это? Если да, есть идеи, как это сделать лучше всего? В противном случае, каким образом это можно сделать?

Также: решение msdn работает в разных браузерах? Наш редактор работает только в Windows, но люди используют IE, Fx, GC и Opera.

Ответы [ 3 ]

3 голосов
/ 24 апреля 2009

Если вам нужна ссылка для работы в любом средстве просмотра, да, регистрация обработчика протокола - лучший способ.

Что касается запуска редактора, вы можете реализовать его как внепроцессный COM-сервер , но если у вас уже отсортирован синтаксический анализ командной строки, вы также можете использовать a сообщение окна или именованный канал, чтобы передать это редактору. Если вы отправляете сообщение окна, вы можете использовать FindWindow (с уникальным именем класса) для проверки работающего экземпляра.

1 голос
/ 24 апреля 2009

Похоже, вы уже решили это, проверив предыдущий экземпляр.

Я был бы удивлен, если бы ОС взяла на себя обязательство каким-либо образом «помечать» связь с данными, сообщая об этом отдельным программам, которые должны запускаться несколько раз, из программ, которые не должны.

0 голосов
/ 26 октября 2015

Вот как я это решил. В основном, есть две части. Или три.

Во-первых, приложение должно зарегистрироваться в реестре, как это. Потребовалось немного погуглить, чтобы узнать, как использовать функции регистрации окон, но они были довольно просты. После добавления этого в реестр ваше приложение будет запущено при нажатии на ссылку с вашим настраиваемым протоколом 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];
 };

}
...