Текущий архив: 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.53 MB
Время: 0.05 c