![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как обработать сообщение
Юрий_К © (2007-08-14 23:31:00)Добавkztvм к примеру в контекстное меню в подменю "Open With" функцией InsertMenuItem свой пункт с WMID = 1111 и со строкой названия некоторой программы (например Notepad). В листбоксе с названиями файлов по правой кнопке вызывается меню и по нажатию на этот пункт подменю та программа должна начать работу с этим файлом. Как эту обработку сообщения WM_COMMAND с WMID = 1111 добавить в основную программу на Delphi, где этот листбокс и находится?
Leonid Troyanovsky (2007-08-17 06:17:00) [1]
> Юрий_К (17.08.07 00:11) [24]
> В догонку, как узнавать связанные с расширением файла программы?
> Функция есть или в реестр нужно лезть?
FindExecutable
AssocQueryString
--
Regards, LVT.
Юрий_К (2007-08-17 00:11:00) [2]В догонку, как узнавать связанные с расширением файла программы? Функция есть или в реестр нужно лезть?
Leonid Troyanovsky (2007-08-16 19:26:00) [3]
> Юрий_К (16.08.07 19:07) [20]
> Возможно не хватало MIIM_ID для передачи ID = 1001 в начальном
> коде, тип передавлся, а ID наверное нет.
Ага, оно.
--
Regards, LVT.
Leonid Troyanovsky (2007-08-16 19:24:00) [4]
> Юрий_К (16.08.07 18:09) [17]
> наверное потому он и не может вернуть клик на итем подменю
Вернет, тут все нормально.
--
Regards, LVT.
Leonid Troyanovsky (2007-08-16 19:22:00) [5]
> Юрий_К (16.08.07 17:09) [12]
> MENUITEMINFO mii = {
> sizeof(mii),
> MIIM_TYPE,
MIIM_TYPE | MIIM_ID ?
--
Regards, LVT.
Юрий_К (2007-08-16 19:07:00) [6]Возможно не хватало MIIM_ID для передачи ID = 1001 в начальном коде, тип передавлся, а ID наверное нет.
Юрий_К (2007-08-16 19:03:00) [7]Стал получать 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 18:20:00) [8]GetLastError даёт ноль. Может неправильно заполняю MENUITEMINFO mii ? Не знаю.
Юрий_К (2007-08-16 18:09:00) [9]TrackPopupMenu вызывается с хэндлом основного меню (hPopupMenu), наверное потому он и не может вернуть клик на итем подменю (hSubMenu), но могу и ошибаться. Пока это соображение. GetLastError буду сейчас смотреть.
Lacmus (2007-08-16 17:56:00) [10]>Юрий_К
HKEY_CLASSES_ROOT\.bmp\OpenWithList
HKEY_CLASSES_ROOT\Applications\mspaint.exe\SupportedTypes
Не решит задачу ? (bmp для примера)
Leonid Troyanovsky (2007-08-16 17:44:00) [11]
> Юрий_К (16.08.07 17:18) [14]
> Понял, что нужно смотреть на результат TrackPopupMenu, но
> сейчас он возвращает 0.
А что говорит GetLastError?
--
Regards, LVT.
Юрий_К (2007-08-16 17:18:00) [12]Понял, что нужно смотреть на результат TrackPopupMenu, но сейчас он возвращает 0.
Юрий_К (2007-08-16 17:11:00) [13]Оставил вставку строки "Notepad", не вырезал. Так что вся функция.
Юрий_К (2007-08-16 17:09:00) [14]и далее ( без вставки строки "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 16:57:00) [15]Программа основная на Дельфи и начинал её не я, но какая-то функциональность и в ДЛЛ-ях прописана, в том числе и показ контекстного меню по клику правой кнопки мышки на листбоксе с названиями файлов. В ДЛЛ передаются координаты курсора мышки и там меню показывается.
Вот начало кода той функции:
// Строим полное имя файла/каталога
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) {
Leonid Troyanovsky (2007-08-16 16:24:00) [16]
> Юрий_К (16.08.07 16:13) [9]
> Хук нужно делать именно из ДЛЛ? Линк на пример имеется ли?
Ну, как я понял, функциональность добавляется к программе
на дельфи из длл на сях. Сл-но, именно из длл.
Только, ставить ее надо один (первичный) гуи поток.
--
Regards, LVT.
Юрий_К (2007-08-16 16:13:00) [17]Leonid Troyanovsky:
"Поэтому, для поиска нужного окна из dll, видимо,
потребуется хук (для отлова WM_INITMENUPOPUP)."
Хук нужно делать именно из ДЛЛ? Линк на пример имеется ли?
Leonid Troyanovsky (2007-08-16 15:21:00) [18]
> Юрий_К (16.08.07 00:15) [5]
> Нет захода в функцию TFormMain.WMCommand вообще.
Сообщения от popupmenu, во-ще-то, шлются специальному окну
объекта PopupList (приложения).
Поэтому, для поиска нужного окна из dll, видимо,
потребуется хук (для отлова WM_INITMENUPOPUP).
Тогда можно получить и хендл меню и окно диспетчера.
--
Regards, LVT.
Юрий_К (2007-08-16 14:44:00) [19]В protected части формы так и объявлено, вроде бы этого достаточно.
umbra (2007-08-16 11:10:00) [20]
procedure TFormMain.WMCommand(var Message: TWMCommand); message WM_COMMAND;