Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Igors от Сентябрь 13, 2014, 08:03



Название: QFileOpenEvent ? [решено]
Отправлено: Igors от Сентябрь 13, 2014, 08:03
Добрый день

Пользователь сделал  double-click на файл моего приложения. Прописал куда положено что умею открывать файлы с таким extension (на Вындоуз в реестр). Приложение запускается, в командной строке пусто.

Цитировать
The QFileOpenEvent class provides an event that will be sent when there is a request to open a file or a URL.
Думаю вот хорошо! Читаю дальше
Цитировать
Note: This class is currently supported for Mac OS X and Symbian only.
А что же на Вындоуз? Прорываться в нативняке ? :'( :'(

Спасибо


Название: Re: QFileOpenEvent ?
Отправлено: Old от Сентябрь 13, 2014, 08:28
Нас сколько я помню имя файла передается в командной строке при запуске приложения связанного с файлом.


Название: Re: QFileOpenEvent ?
Отправлено: Igors от Сентябрь 13, 2014, 08:32
Нас сколько я помню имя файла передается в командной строке при запуске приложения связанного с файлом.
Пусто (Win 7). И непринципиально - юзер может открывать когда приложение уже запущено.
Ищу какая это месяга  :'(


Название: Re: QFileOpenEvent ?
Отправлено: Igors от Сентябрь 13, 2014, 10:37
Нет, не пусто, в командной строке приходит (то я в реестре насвистел). Но это не помогает если приложение уже стартовало. Вроде надо действовать через WM_DDE_INITIATE?

[off]
Где тот молодой-интересный называющий себя виндоузятником? Как до дела доходит - ветром сдувает  :)
[/off]


Название: Re: QFileOpenEvent ?
Отправлено: Bepec от Сентябрь 13, 2014, 10:44
Я вас особо не люблю, потому и не отписываюсь без призыва.
Очевидно:  на деле это должно поддерживаться приложением.
Варианты:
1) одно приложение за раз - запуск второго передаёт параметры в первый.
2) COM длл, которая будет передавать параметры приложению.

А если вы хотите, чтобы ОС правило код вашего приложения, то вы будете разочарованы. Именно вы должны добавить поддержку. 


Название: Re: QFileOpenEvent ?
Отправлено: Igors от Сентябрь 13, 2014, 11:36
Варианты:
1) одно приложение за раз - запуск второго передаёт параметры в первый.
2) COM длл, которая будет передавать параметры приложению.
Такие рекомендации недоступны моему пониманию  :)

Ладно, начнем от печки. Есть расширение напр .da1 (мое). Прописываю в HKEY_CLASSES_ROOT

Ключ  Значение
.da1    MyApp_da1

Теперь создаю там же,  в HKEY_CLASSES_ROOT

MyApp_da1
     DefaultIcon       C:\Test\MyApp.exe,3
     shell
             open
                     command  C:\Test\MyApp.exe %1
                     ddeexec                              Open(%1)
                               application                 MyApp
                               topic                         system
 
Это работает, Если приложение уже запущено, то по крайней мере WM_DDE_INITIATE приходит. Если нет - запускается, и я получаю имя файла в командной строке. но при этом появляется неприятный варнинг в Explorer'e 
Цитировать
Тhere was a problem sending the command to the program

Если убрать секцию ddeexec, варнинг исчезает, но и WM_DDE_INITIATE не приходит

ЧЯДНТ ?




Название: Re: QFileOpenEvent ?
Отправлено: kambala от Сентябрь 13, 2014, 12:43
с QtSingleApplication все работает идеально, и даже QFileOpenEvent приходит на маке

кстати по-хорошему надо оба параметра command брать в кавычки: command  "C:\Test\MyApp.exe" "%1"


Название: Re: QFileOpenEvent ?
Отправлено: Bepec от Сентябрь 13, 2014, 12:47
Беглый просмотр сообщения показывает, что оно должно использоваться клиентами для соединения с сервером. Подразумевается что сервер в момент посыла сообщения УЖЕ запущен и ожидает команду.

Так же на некоторых форумах рекомендуют не использовать этот механизм, т.к. он устаревший.

Собственно именно из-за  "устаревания" этот метод прошёл мимо моих глаз :)

PS а на сей день работают без сомнений способы, указанные в предыдущем моём сообщении.


PPS если не понятно то
1) приложение при запуске проверяет, запущен ли ещё 1 его экземпляр и если запущен, то передаёт туда данные и закрывается.
2) COM dll, которая в принципе будет делать то же, что и в п.1. Правда 100% гарантии не даю - этим способом не пользовался.


Название: Re: QFileOpenEvent ?
Отправлено: Igors от Сентябрь 13, 2014, 13:23
с QtSingleApplication все работает идеально, и даже QFileOpenEvent приходит на маке
На маке я и так сделал  :)

кстати по-хорошему надо оба параметра command брать в кавычки: command  "C:\Test\MyApp.exe" "%1"
Только что получил за отсутствие кавычек, исправил. Но тут др беда - на Вындоуз когда юзер выбрал 2 или более файлов и правой кнопкой Open - в командной строке только первый. Пробовал %* (вместо %1) - не помогло

Беглый просмотр сообщения показывает,
Наверное речь идет о сообщении WM_DDE_INITIATE. Хорошо, устарело, что вместо него?

PS а на сей день работают без сомнений способы, указанные в предыдущем моём сообщении.

PPS если не понятно то
1) приложение при запуске проверяет, запущен ли ещё 1 его экземпляр и если запущен, то передаёт туда данные и закрывается.
2) COM dll, которая в принципе будет делать то же, что и в п.1. Правда 100% гарантии не даю - этим способом не пользовался.
В любом случае приложение должно что-то получить (напр сигнал, месягу, event), иначе как оно узнает что нужно открыть файл? Причем тут 2-я instance - хз. И вообще неясно о чем Вы  :)


Название: Re: QFileOpenEvent ?
Отправлено: Old от Сентябрь 13, 2014, 13:38
В любом случае приложение должно что-то получить (напр сигнал, месягу, event), иначе как оно узнает что нужно открыть файл? Причем тут 2-я instance - хз. И вообще неясно о чем Вы  :)
Ну так вам и предлагают отправлять сигнал, месягу, event от одной instance программы другой.
Запущенных программ нет. Пользователь кликнул на файле с данными - запустилась первая instance вашей программы. Теперь пользователь кликнут на другом файл с данными - стартует вторая instance вашей программы - она определяет, что запущенна первая instance - она отправляет сигнал, месягу, event с именами файлов этой первой instance - вторая instance завершается.
Поэтому и про QtSingleApplication упомянули.


Название: Re: QFileOpenEvent ?
Отправлено: Igors от Сентябрь 14, 2014, 10:35
Ну так вам и предлагают отправлять сигнал, месягу, event от одной instance программы другой.
Запущенных программ нет. Пользователь кликнул на файле с данными - запустилась первая instance вашей программы. Теперь пользователь кликнут на другом файл с данными - стартует вторая instance вашей программы - она определяет, что запущенна первая instance - она отправляет сигнал, месягу, event с именами файлов этой первой instance - вторая instance завершается.
Поэтому и про QtSingleApplication упомянули.
Спасибо, теперь понял. Решил что проще использовать этот механизм чем возиться с DDE, делаю.
Проблема: запуск происходит только "по одному". Напр юзер выбрал 8 файлов Open - запускается 8 instances, причем асинхронно. Как бы сделать чтобы в командной строке приходили все?

Спасибо


Название: Re: QFileOpenEvent ?
Отправлено: Igors от Сентябрь 14, 2014, 12:31
Как бы сделать чтобы в командной строке приходили все?
Погуглил, тоже люди спрашивают, но видимо в этой чудесной ОС такого нету. Ну ладно, сделал через QSharedMemory, там тривиально. Работает

Спасибо


Название: Re: QFileOpenEvent ? [решено]
Отправлено: Bepec от Сентябрь 14, 2014, 12:45
Групповая обработка только через COM дллку. Что скажем так не прельщает. Но механизм "передачи в 1 инстанс" и в этом случае работает нормально.


Название: Re: QFileOpenEvent ? [решено]
Отправлено: OKTA от Сентябрь 15, 2014, 09:25
Я делал так, что запускается маленькое приложенице, основанное на QtSingleApplication и оно ждет какое-то количество миллисекунд, когда придут данные обо всех остальных запущенных копиях и уже после этого запускаю основное приложение, куда кидаю все данные накопленные.

А чтобы все приходило за один раз - по простому не сделать  :-\


Название: Re: QFileOpenEvent ? [решено]
Отправлено: Igors от Сентябрь 15, 2014, 10:54
Я делал так, что запускается маленькое приложенице, основанное на QtSingleApplication и оно ждет какое-то количество миллисекунд, когда придут данные обо всех остальных запущенных копиях и уже после этого запускаю основное приложение, куда кидаю все данные накопленные.

А чтобы все приходило за один раз - по простому не сделать  :-\
Хз как можно такое придумать "запуск копии на КАЖДЫЙ" - но это факт :) У меня примерно так (псевдокод)

Код
C++ (Qt)
QSharedMemory theSharedMem;
 
struct CSharedData {
int mType. mVers;
HWND mWnd;
char mDummy[4];
};
UINT theMsgID = 0;
------------
theMsgID = ::RegisterWindowMessage(GetAppFullName());
 
theSharedMem.setName(GetAppFullName());
if (theSharedMem.create(SHARED_SIZE)) {    // рабочая копия
theSharedMem.lock();
CSharedData * sd =  (CSharedData *) theSharedMem.data();
memset(sd, 0, SHARED_SIZE);
sd.mType = DATA_TYPE;  // инициализация
sd.mVers = DATA_VERS;
theSharedMem.unlock();
}
 
else  
if (theSharedMem.attach()) {      // копия для передачи командной строки
bool stop = false;
while (!stop) {
 theSharedMem.lock();
 CSharedData * sd =  (CSharedData *) theSharedMem.data();
  if (sd->mWnd) {
    // добавляем командную строку
   ...
   stop = true;
   ::PostMessage(sd->mWnd, theMsgID, 0, 0):
  }
 theSharedMem.unlock();
 if (!stop) ::Sleep(10);   // ждем когда появится mWnd
}
exit(0);
}
 


Название: Re: QFileOpenEvent ? [решено]
Отправлено: OKTA от Сентябрь 15, 2014, 11:12
Что-то как-то совсем сложно) QtSingleApplication при запуске позволяет проверить, запущено ли уже это приложение. 
В итоге все умещается примерно в
Код:
int main(int argc, char *argv[])
{
    QtSingleApplication app(argc, argv, false);

    if(app.isRunning()) {
        //

        app.sendMessage(передаем параметры из argv);
        return 0;
    }

    ContextManager cm;
   
    QTimer::singleShot(500, &cm, SLOT(timeout())); // подождали пол секунды и запустили главное приложение

    QObject::connect(&app, SIGNAL(messageReceived(QString)), // накапливаем argv из всех запросов на запуск приложения
                     &cm, SLOT(messageReceived(QString)));

    return app.exec();
}


Название: Re: QFileOpenEvent ? [решено]
Отправлено: Igors от Сентябрь 15, 2014, 11:48
Что-то как-то совсем сложно) QtSingleApplication при запуске позволяет проверить, запущено ли уже это приложение. 
В итоге все умещается примерно в
Я туда смотрел, но меня смутил этот линк (http://qt-project.org/forums/viewthread/22994)
И этот шматок нативняка такая мелочь по сравнению с тем что было без Qt  :)


Название: Re: QFileOpenEvent ? [решено]
Отправлено: OKTA от Сентябрь 15, 2014, 11:55
А, ну насчет пятерки не знаю, я все еще на 4  ;D
А тут вроде пофиксенные исходники лежат кстати https://qt.gitorious.org/qt-solutions/lgeyers-qt-solutions/source/c50d0f3f142606b823f9106c7cd8b9a7d066e6ff:qtsingleapplication