На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела FAQ в группе разделов С++.
1. Раздел FAQ предназначен для публикации готовых статей.
2. Здесь нельзя задавать вопросы, для этого существуют соответствующие разделы:
Чистый С++
Visual C++ / MFC / WTL / WinApi
Borland C++ Builder
COM / DCOM / ActiveX / ATL
Сопутствующие вопросы
3. Внимание, все темы и сообщения в разделе премодерируются. Любое сообщение или тема будут видны остальным участникам только после одобрения модератора.
Модераторы: B.V., Qraizer
  
> Передать строчку в другое приложение , SendMessage + GlobalAddAtom
    Передать строку в другое приложение посредством сообщений WINDOWS
    Добрый день(или утро, или вечер).

    Недавно я столкнулся с проблемой передачи строки в другое приложение.
    Задача состояла вот в чем:
    1. Проанализировать есть ли уже запущенные экземпляры
    программы.
    2. Если есть то передать управление уже запущенной программе.
    3. Если пользователь пытается открыть файл то передать запущенной
    программе строку с именем файла.
    4. Закрыть текущий экземпляр в случае успешных предидущих действий.

    Я решил сразу использовать метод передачи сообщений от окна к окну.
    И тут случилось...

    Посредством SendMessage очень легко передавать САМУ МЕССАГУ и два целых
    числа (WPARAM)+(LPARAM).
    А чтобы передать строчку.... Пришлось "повозиться".
    Предложенные варианты решения меня не очень устроили в связи со своей
    громоздкостью.

    Подумав решил использовать ГЛОБАЛЬНУЮ ТАБЛИЦУ АТОМОВ.
    Привожу пример кода. с краткими пояснениями.

    ExpandedWrap disabled
      //Приложение запускающее мессагу
       
      //Регестрируем сообщение
      extern  UINT MY_FILES_MSG1 = ::RegisterWindowMessage("MY_FILES_MSG");
      .......
      //Код описанный в процедуре CMyApp::InitInstance
      CString cap ;
      cap.LoadString(IDR_MAINFRAME);
      //Ищем уже запущенное приложение по окошку
      CWnd *pwnd = CWnd::FindWindow(NULL,cap);
      if (pwnd !=NULL)
      {
      //Если нашли то вперед запускать нашу мессагу
      pwnd->ShowWindow(SW_RESTORE);
      pwnd->SetForegroundWindow();
       
      // CString cs = AfxGetApp()->m_lpCmdLine;
       
      //ЧИТАЕМ преданный файл
      //вы вместо файла можете отправить все что угодно
      CCommandLineInfo cl;
         ParseCommandLine(cl);
          if(strlen(cl.m_strFileName)>1)
          {
           UINT _len = GlobalAddAtom(cl.m_strFileName);
          ::SendMessage(pwnd->m_hWnd,MY_FILES_MSG,strlen(cl.m_strFileName)+1,_len);
          }
          return false;
      }
       
       
       
      //Код приложения принимающей сообщение
       
       
      //Регестрируем сообщение
      extern  UINT MY_FILES_MSG2 = ::RegisterWindowMessage("MY_FILES_MSG");
       
      // В описании класса окна обязательно  надо указать нашу
      //процедуру для обработки сообщения
       
      protected:
          //{{AFX_MSG(CMainFrame)
                  ...
          afx_msg LRESULT OnFileMessage(WPARAM wParam, LPARAM lParam);
          ....
                  //}}AFX_MSG
          DECLARE_MESSAGE_MAP()
       
       
      BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
          //{{AFX_MSG_MAP(CMainFrame)
      ......
      //Макрос МФС  ON_REGISTERED_MESSAGE предназначен для сопряжения
      //Нашей мессаги с процедурой обработки (Крутая штука)
      ON_REGISTERED_MESSAGE(MY_FILES_MSG2, OnFileMessage)
      .......
          //}}AFX_MSG_MAP
      END_MESSAGE_MAP()
       
       
      //Обработчик нашей процедуры.
      LRESULT CMainFrame::OnFileMessage(WPARAM wParam, LPARAM lParam)
      {
          LPCTSTR ls;
          if(wParam>0) //Если нашлась  "длина"
          {
             LPSTR b =new TCHAR[wParam];  //Создаем буфер
              int _len = wParam;
              GlobalGetAtomName(lParam,b,_len); //Исчем строчку по ИНДЕКСУ АТОМА
              ls = (LPCTSTR)b;  //Переводим в выгодный и простой (для нас) формат
              GlobalDeleteAtom(lParam); //Удаляем АТОМ, если конечно он уже не нужен
               CreatCld(ls);//Процедура обрабатывающея строчку
                                      // Вы можете вписать сюда все что угодно
               delete b;//Чистим память.
          }
          return 0;
      }

    Вся суть заключается в следующем.
    Одна прога ложит в ГТА строку и передает уникальный
    идентификатор АТОМА(WPARAM) + (Длину заложенной Строки)(LPARAM) Другой проге.
    Посредством сообщения другая прога "разжовует" сообщение и принимает некоторые действия.

    Статья предназначена пояснить лишь принцип передачи.
    А ШЕДЕВРЫ - ТВОРИТЬ ПРИЙДЕТСЯ ВАМ.
    Все вопросы на aster_x@inbox.ru
      Красивый велосипед. А не пробовал просто через WPARAM передать свой HINSTANCE, через LPARAM - указатель на строку, потом открыл процесс и ReadProcessMemory? Или еще проще, заюзать WM_COPYDATA? К тому же вроде бы в МФЦ прозрачно то, что ты описал, делается через DDE...
        barazuk
        А HINSTANCE-то зачем? :wacko:
          Тьфу, блин, о другом задумался... Конечно, ID процесса...
            А если надо в разное время выполнения программ юзать одну и туже строку на разных приложениях.
            На разных уровнях и к примеру с зарытым реестром а файловую систему юзать нельзя.
            WM_COPYDATA Мне предлагали и что... Вот кульно отрпавлять КОНСОЛЬНЫМ приложениям виндовые мессаги...

            ReadProcessMemory А если прога полчаса назад закрыта....

            Тем более повторюсь

            Предложенные варианты решения меня не очень устроили в связи со своей
            громоздкостью.

            И тем более я не борюсь за получение права на новый ВЕЛОСИПЕД я просто предложил один из методов.
              Да метод как метод, ничем не лучше и не хуже чем другие. Единственное, ты забыл указать очень важное ограничение на твой метод:
              Цитата
              ...The string can have a maximum size of 255 bytes....

              И, не путай людей. GlobalAddAtom возвращает не длину, а идентификатор вставленного (либо уже находящегося) атома.
              Сообщение отредактировано: Ace -
                Ace я понял Спасибо
                просто идентификатор АТОМА(WPARAM) + (Длину заложенной Строки) в (LPARAM)


                И для остальных....

                Немного теории...
                Data Exchange - Обмен данными(В переводе с английского).
                Dynamic Data Exchange - Динамический Обмен данными.
                Если быть уже совсем точным то...

                К протоколу Data Excange относятся следующие компонентные методики операционной
                системы MS Windows.

                1) Атомы
                2)Буфер обмена
                3)Копирование данных посредством COPYDATA & WM_COPYDATA
                4)Как вы уже упянули ... это DDE
                к которыму якобы относятся GAT Глобальная таблица атомов.
                Извините но мне кажется что вы немного ошиблись, и метод COPYDATA
                может быть и приемлем но он также я вляется "дочерним подклассом"
                Системы обмена данными WINDOWS.
                Так что ТАБЛИЦА АТОМОВ не является подситемой DDE. А может я ошибаюсь вместе с MICROSOFT???????????????


                P.S. А вполне может быть, что мы немного ошибаемся (вместе MICROSOFT).
                  Цитата aster_x @
                  ReadProcessMemory А если прога полчаса назад закрыта....


                  Цитата aster_x @
                  ::SendMessage(pwnd->m_hWnd,MY_FILES_MSG,strlen(cl.m_strFileName)+1,_len);


                  Т.е. твоя полчаса назад закрытая программа посылает другой программе, которая еще не открылась, это сообщение? Или как правильно понять твою логику?

                  WM_COPYDATA кстати, по-моему, можно обработать и после "смерти" пославшей проги, там данные копируются (Гуру! Поправьте, если гоню...)
                    Цитата aster_x @
                    Немного теории...
                    Data Exchange - Обмен данными(В переводе с английского).
                    Dynamic Data Exchange - Динамический Обмен данными.
                    Если быть уже совсем точным то...

                    К протоколу Data Excange относятся следующие компонентные методики операционной
                    системы MS Windows.


                    Не совсем понял, к чему это все... Я просто обратил внимание, что в примере была использована связка MSVS+MFC. И мне показалось достаточно странным не использовать встроенный механизм поддержки ДДЕ через комстроку для открытия всех документов в одном экземпляре приложения. См. тупейший (сразу прошу прощения у эстетов - потратил на креатив целых пять минут, так что не взыщите...) пример в аттаче.
                    Сообщение отредактировано: barazuk -

                    Прикреплённый файлПрикреплённый файлTestDDE.rar (88.24 Кбайт, скачиваний: 238)
                      Цитата barazuk @
                      WM_COPYDATA кстати, по-моему, можно обработать и после "смерти" пославшей проги, там данные копируются

                      Смотря когда смерть произошла.
                      Цитата
                      While this message is being sent, the referenced data must not be changed by another thread of the sending process.
                        Цитата barazuk @
                        механизм поддержки ДДЕ через комстроку для открытия всех документов

                        Скорее всего подразумевается коммандная строка.
                        В том то и дело что пришлось не открывыать новое приложнение а из старого забирать комстроку.
                        И отправлять уже запущенной копии.
                          Цитата aster_x @
                          Скорее всего подразумевается коммандная строка.
                          В том то и дело что пришлось не открывыать новое приложнение а из старого забирать комстроку.
                          И отправлять уже запущенной копии.


                          Блин, дак никто ничего и не открывает, если уже есть запущенное приложение!

                          Просто твоя вторая копия при наличии первой ничего не делает, а только посылает через DDE сообщение открыть файл (или что ты захочешь) первой. ВСЕ! Встроено в MFC уже лет пятнадцать как. Покрути приложенный пример, и все станет ясно.
                            Цитата aster_x @
                            2. Если есть то передать управление уже запущенной программе.
                            3. Если пользователь пытается открыть файл то передать запущенной
                            программе строку с именем файла.
                            4. Закрыть текущий экземпляр в случае успешных предидущих действий.


                            Цитата aster_x @
                            В том то и дело что пришлось не открывыать новое приложнение а из старого забирать комстроку.
                            И отправлять уже запущенной копии.


                            Что ты сказать то хотел? Сам не запутался? :)
                              Нет не запутался. И еще я не претендую на монопольное содержание метода
                              кто как хочет тот так и делает. ОСНОВНЫЕ ПРИНЦИПЫ Демократии и MICROSOFT.
                              А может быть я ошибаюсь(Вместе с MICROSOFT) :)
                              1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                              0 пользователей:


                              Рейтинг@Mail.ru
                              [ Script execution time: 0,0466 ]   [ 14 queries used ]   [ Generated: 15.05.24, 20:16 GMT ]