Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];

Вниз

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

 
Юрий_К   (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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.048 c
15-1191497367
Crazybobr
2007-10-04 15:29
2007.10.28
Таможенный ставки для чайника. Просьба помочь.


2-1189885813
vasIZmax
2007-09-15 23:50
2007.10.28
ini-file


2-1191588575
olevacho_
2007-10-05 16:49
2007.10.28
Представление данных


15-1191578295
Германн
2007-10-05 13:58
2007.10.28
С Днем Учителя!


2-1191493300
F@T@L_Err0r
2007-10-04 14:21
2007.10.28
изменение разрешения





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский