Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.10.28;
Скачать: CL | DM;

Вниз

Как обработать сообщение   Найти похожие ветки 

 
Юрий_К   (2007-08-14 23:31) [0]

Добавkztvм к примеру в контекстное меню в подменю "Open With" функцией InsertMenuItem свой пункт с WMID = 1111 и со строкой названия некоторой программы (например Notepad). В листбоксе с названиями файлов по правой кнопке вызывается меню и по нажатию на этот пункт подменю та программа должна начать работу с этим файлом. Как эту обработку сообщения WM_COMMAND с WMID = 1111 добавить в основную программу на Delphi, где этот листбокс и находится?


 
DrPass ©   (2007-08-14 23:47) [1]

Ну... если исходников нет, то
а) Внедрить туда свою DLL, с ее помощью подменить оконную функцию той формы, в новой оконной функции обрабатывать WM_COMMAND либо в остальных случаях передавать управление старой оконной функции
Если исходники есть, то
б) добавить к ее форме обработчик WM_COMMAND и перекомпилировать


 
Юрий_К   (2007-08-15 13:41) [2]

"б) добавить к ее форме обработчик WM_COMMAND и перекомпилировать"

Добавить как? Просто этого делать не приходилось. Обработка сообщений происходить в модуле Forms, не туда же добавлять.


 
DrPass ©   (2007-08-15 13:44) [3]

Delphi позволяет добавлять произвольные обработчики сообщений Windows, см. директиву message


 
Юрий_К   (2007-08-16 00:13) [4]

Не помогло, не знаю, что не так.
Коды такие:
В ДЛЛ на СИ, вызывается программой на Дельфи.

                 if (nOpenWith >= 0)
                 {
                   char szText[] = "Notepad";
                  MENUITEMINFO mii = {
                   sizeof(mii),
                   MIIM_TYPE,
                   MFT_STRING,
                   0,
                   wmID,
                   0,
                   0,
                   0,
                   0,
                   szText,
                     sizeof(szText)};
                   InsertMenuItem(hSubMenu, nCnt, true, &mii);
                   
                 }

В программе на Дельфи.

procedure TFormMain.WMCommand(var Message: TWMCommand);
var sPath: string;
begin
 if (Message.ItemID = 1111) then
 begin
   sPath := lstFiles.Items[lstFiles.ItemIndex];
   ShellExecute(0, "open", "notepad.exe", PCHAR(sPath), nil, SW_SHOWNORMAL);
 end
 else
   inherited;
end;


 
Юрий_К   (2007-08-16 00:15) [5]

Нет захода в функцию TFormMain.WMCommand вообще.


 
umbra ©   (2007-08-16 11:10) [6]

procedure TFormMain.WMCommand(var Message: TWMCommand); message WM_COMMAND;


 
Юрий_К   (2007-08-16 14:44) [7]

В protected части формы так и объявлено, вроде бы этого достаточно.


 
Leonid Troyanovsky ©   (2007-08-16 15:21) [8]


> Юрий_К   (16.08.07 00:15) [5]

> Нет захода в функцию TFormMain.WMCommand вообще.

Сообщения от popupmenu, во-ще-то, шлются специальному окну
объекта PopupList (приложения).

Поэтому, для поиска нужного окна из dll, видимо,
потребуется хук (для отлова WM_INITMENUPOPUP).
Тогда можно получить и хендл меню и окно диспетчера.

--
Regards, LVT.


 
Юрий_К   (2007-08-16 16:13) [9]

Leonid Troyanovsky:
"Поэтому, для поиска нужного окна из dll, видимо,
потребуется хук (для отлова WM_INITMENUPOPUP)."

Хук нужно делать именно из ДЛЛ? Линк на пример имеется ли?


 
Leonid Troyanovsky ©   (2007-08-16 16:24) [10]


> Юрий_К   (16.08.07 16:13) [9]

> Хук нужно делать именно из ДЛЛ? Линк на пример имеется ли?

Ну, как я понял, функциональность добавляется к программе
на дельфи из длл на сях. Сл-но, именно из длл.
Только, ставить ее надо один (первичный) гуи поток.

--
Regards, LVT.


 
Юрий_К   (2007-08-16 16:57) [11]

Программа основная на Дельфи и начинал её не я, но какая-то функциональность и в ДЛЛ-ях прописана, в том числе и показ контекстного меню по клику правой кнопки мышки на листбоксе с названиями файлов. В ДЛЛ передаются координаты курсора мышки и там меню показывается.
Вот начало кода той функции:

 // Строим полное имя файла/каталога
 TCHAR tchFullPath[MAX_PATH]; DWORD size = sizeof(tchFullPath)/sizeof(TCHAR);
 DWORD dwres = GetFullPathName(szPath, size, tchFullPath, NULL);
 if (dwres == 0 || dwres >= size) return FALSE;
 // Получаем интерфейс IShellFolder рабочего стола
 IShellFolder *pDesktopFolder = NULL;
 if (SHGetDesktopFolder(&pDesktopFolder) != NOERROR) return FALSE;
 IShellFolder *pFolder = NULL; IContextMenu *pContextMenu = NULL;
 // Преобразуем заданный путь в LPITEMIDLIST
 LPITEMIDLIST pidl=NULL; size = 2*MAX_PATH; OLECHAR olePath[2*MAX_PATH];
 dwres = MultiByteToWideChar(CP_ACP, 0, tchFullPath, -1, olePath, size);
 if (dwres > 0 && dwres < size) {
   HRESULT hres = pDesktopFolder->ParseDisplayName(hWnd, NULL, olePath, NULL, &pidl, NULL);
   //DWORD scode = GetScode(hres);
   if (hres == NOERROR) {
     // Ищем последний идентификатор в полученном списке pidl
     LPITEMIDLIST pLastId = pidl; USHORT temp;
     while(1)
     {
      int offset = pLastId->mkid.cb;
      temp = *(USHORT*)((BYTE*)pLastId + offset);
      if(temp == 0) break;
      pLastId = (LPITEMIDLIST)((BYTE*)pLastId + offset);
     }  
     // Получаем интерфейс IShellFolder родительского объекта для заданного файла/каталога
     // Примечание: родительский каталог идентифицируется списком pidl за вычетом последнего
     //             элемента, поэтому мы временно зануляем pLastId->mkid.cb, отрезая его от списка
     temp = pLastId->mkid.cb;
     pLastId->mkid.cb = 0;
     if (pDesktopFolder->BindToObject(pidl, NULL, IID_IShellFolder,
                                                 (void**)&pFolder) == NOERROR) {
       // Получаем интерфейс IContextMenu для заданного файла/каталога
       // Примечание: относительно родительского объекта заданный файл/каталог идентифицируется
       //             единственным элементом pLastId
       pLastId->mkid.cb = temp;
       if (pFolder->GetUIObjectOf(hWnd, 1, (LPCITEMIDLIST *)&pLastId, IID_IContextMenu, NULL,
                                            (void**)&pContextMenu) == NOERROR) {
         // Создаём меню
         HMENU hPopupMenu = CreatePopupMenu();
         if (hPopupMenu) {


 
Юрий_К   (2007-08-16 17:09) [12]

и далее ( без вставки строки "Notepad", dsht

         if (hPopupMenu) {
           // Заполняем меню
           pContextMenu->QueryContextMenu(hPopupMenu, 0, 1, 0x7FFF, 0);
           // После первого разделителя все итемы удаляем
           ULONG i = 0, nCount = GetMenuItemCount(hPopupMenu)-1;
           bool fdel = false; char szBuf[MAX_PATH];
           while(i < nCount) {
            if (GetMenuString(hPopupMenu, i, NULL, 0, MF_BYPOSITION) >= MAX_PATH) {
              i++; continue;
            }
            GetMenuString(hPopupMenu, i, szBuf, MAX_PATH, MF_BYPOSITION);
            if (szProgramm)
            if (!_stricmp(szBuf, szOpenWith))
            {
               HMENU hSubMenu = GetSubMenu(hPopupMenu, i);
               if (hSubMenu == NULL) ;
               else
               {
                 int j = 0, nOpenWith = -1;
                 int nCnt = GetMenuItemCount(hSubMenu);
                 while(j < nCnt)
                 {
                   if (GetMenuString(hSubMenu, j, NULL, 0, MF_BYPOSITION) >= MAX_PATH) {
                     j++; continue;
                   }
                   GetMenuString(hSubMenu, j, szBuf, MAX_PATH, MF_BYPOSITION);
                   if (!_stricmp(szBuf, szOpenWith))
                   {
                     nOpenWith = j; break;
                   }
                   j++;
                 }
                 if (nOpenWith >= 0)
                 {
                   char szText[] = "Notepad";
                  MENUITEMINFO mii = {
                   sizeof(mii),
                   MIIM_TYPE,
                   MFT_STRING,
                   MFS_ENABLED,
                   wmID,
                   0,
                   0,
                   0,
                   0,
                   szText,
                     sizeof(szText)};
                   InsertMenuItem(hSubMenu, nCnt, true, &mii);
                   
                 }
                 else
                 {
                 }
               }
            }
            if (fdel) {
              DeleteMenu(hPopupMenu, i, MF_BYPOSITION);
              nCount = GetMenuItemCount(hPopupMenu)-1;
              continue;
            }
            else if (szBuf[0] == 0) fdel = true;
            i++;
           }
           // Отображаем меню
           UINT nCmd = TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_RETURNCMD,
                                      pPoint->x, pPoint->y, 0, hWnd, 0);
           // Выполняем команду (если она была выбрана)
           if(nCmd)
           {
             CMINVOKECOMMANDINFO ici;
             ZeroMemory(&ici, sizeof(CMINVOKECOMMANDINFO));
             ici.cbSize = sizeof(CMINVOKECOMMANDINFO);
             ici.hwnd = hWnd;
             ici.lpVerb = MAKEINTRESOURCE(nCmd-1);
             ici.nShow = SW_SHOWNORMAL;
             pContextMenu->InvokeCommand(&ici);
           }
         }
       }
     }
   }
 }
 // Получаем интерфейс IMalloc
 IMalloc *pMalloc;
 if (SHGetMalloc(&pMalloc) != NOERROR) return FALSE;
 // Освобождаем память, выделенную для pidl
 if (pidl) pMalloc->Free(pidl);
 // Освобождаем все полученные интерфейсы
 if (pDesktopFolder) pDesktopFolder->Release();
 if (pFolder) pFolder->Release();
 if (pContextMenu) pContextMenu->Release();
 pMalloc->Release();
 return TRUE;


 
Юрий_К   (2007-08-16 17:11) [13]

Оставил вставку строки "Notepad", не вырезал. Так что вся функция.


 
Юрий_К   (2007-08-16 17:18) [14]

Понял, что нужно смотреть на результат TrackPopupMenu, но сейчас он возвращает 0.


 
Leonid Troyanovsky ©   (2007-08-16 17:44) [15]


> Юрий_К   (16.08.07 17:18) [14]

> Понял, что нужно смотреть на результат TrackPopupMenu, но
> сейчас он возвращает 0.

А что говорит GetLastError?

--
Regards, LVT.


 
Lacmus ©   (2007-08-16 17:56) [16]

>Юрий_К  

HKEY_CLASSES_ROOT\.bmp\OpenWithList
HKEY_CLASSES_ROOT\Applications\mspaint.exe\SupportedTypes

Не решит задачу ? (bmp для примера)


 
Юрий_К   (2007-08-16 18:09) [17]

TrackPopupMenu вызывается с хэндлом основного меню (hPopupMenu), наверное потому он и не может вернуть клик на итем подменю (hSubMenu), но могу и ошибаться. Пока это соображение. GetLastError буду сейчас смотреть.


 
Юрий_К   (2007-08-16 18:20) [18]

GetLastError даёт ноль. Может неправильно заполняю MENUITEMINFO mii ? Не знаю.


 
Юрий_К   (2007-08-16 19:03) [19]

Стал получать ItemID. Что-то не так заполнял видимо, проблему решил через функцию GetMenuItemInfo.

                 if (nOpenWith >= 0)
                 {
                   char szText[] = "Notepad";
                  MENUITEMINFO mii = {
                   sizeof(mii),
                   MIIM_CHECKMARKS|MIIM_ID|MIIM_DATA|MIIM_STATE|MIIM_SUBMENU|MIIM_TYPE,
                   0,
                   0,
                   0,
                   0,
                   0,
                   0,
                   0,
                   szBuf,
                     sizeof(szBuf)};
                   BOOL f = GetMenuItemInfo(
                       hSubMenu,          
                       nOpenWith,          
                       true,    
                       &mii  
                     );
                   mii.wID = 1001;
                   mii.dwTypeData = szText;
                   mii.cch = sizeof(szText);
                   InsertMenuItem(hSubMenu, nCnt, true, &mii);                    
                 }


 
Юрий_К   (2007-08-16 19:07) [20]

Возможно не хватало MIIM_ID для передачи ID = 1001 в начальном коде, тип передавлся, а ID наверное нет.


 
Leonid Troyanovsky ©   (2007-08-16 19:22) [21]


> Юрий_К   (16.08.07 17:09) [12]

>                   MENUITEMINFO mii = {
>                    sizeof(mii),
>                    MIIM_TYPE,


MIIM_TYPE | MIIM_ID ?

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-08-16 19:24) [22]


> Юрий_К   (16.08.07 18:09) [17]

>  наверное потому он и не может вернуть клик на итем подменю

Вернет, тут все нормально.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-08-16 19:26) [23]


> Юрий_К   (16.08.07 19:07) [20]

> Возможно не хватало MIIM_ID для передачи ID = 1001 в начальном
> коде, тип передавлся, а ID наверное нет.

Ага, оно.

--
Regards, LVT.


 
Юрий_К   (2007-08-17 00:11) [24]

В догонку,  как узнавать связанные с расширением файла программы? Функция есть или в реестр нужно  лезть?


 
Leonid Troyanovsky ©   (2007-08-17 06:17) [25]


> Юрий_К   (17.08.07 00:11) [24]

> В догонку,  как узнавать связанные с расширением файла программы?
>  Функция есть или в реестр нужно  лезть?

FindExecutable
AssocQueryString

--
Regards, LVT.



Страницы: 1 вся ветка

Текущий архив: 2007.10.28;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.023 c
15-1191598424
Nikfel
2007-10-05 19:33
2007.10.28
DVD-Recoder.


4-1177575482
capkoh
2007-04-26 12:18
2007.10.28
Повторное открытие диалога


2-1191401258
User_0
2007-10-03 12:47
2007.10.28
Как записать путь к БД в *.ini(Interbase)


6-1172579067
SergGuk
2007-02-27 15:24
2007.10.28
DDE + сеть


9-1162110637
Zlodey
2006-10-29 11:30
2007.10.28
DelphiX