Я пытался создать программу Visual C++, которая отображает пункт меню, когда пользователь щелкает правой кнопкой мыши, следуя нескольким онлайн-руководствам. Однако, несмотря на регистрацию DLL и перезапуск Проводника Windows, он вообще не работает. Непонятно, чего мне здесь не хватает.
regsvr32.exe ShellExtension.dll тоже работает без проблем.
ShellExtension.h
#pragma once
#include
#include
#include
#include // Adicione isso
#define MYUUID "{6f81fd22-1c80-4619-a401-22d66dc3410b}"
#define NomeDaExtensao "ShellExtension"
#define Title "Shell Extension"
class __declspec(uuid(MYUUID)) ShellExtension : public IShellExtInit, public IContextMenu
{
public:
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IShellExtInit
STDMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID);
// IContextMenu
STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pReserved, LPSTR pszName, UINT cchMax);
private:
ULONG m_cRef;
};
ShellExtension.cpp
#include
#include
#include "ShellExtension.h"
#include "resource.h"
HANDLE g_hEventSource = NULL;
STDMETHODIMP ShellExtension::QueryInterface(REFIID riid, void** ppvObject)
{
if (riid == IID_IUnknown || riid == IID_IShellExtInit || riid == IID_IContextMenu)
{
*ppvObject = this;
AddRef();
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) ShellExtension::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) ShellExtension::Release()
{
ULONG cRef = InterlockedDecrement(&m_cRef);
if (cRef == 0)
delete this;
return cRef;
}
STDMETHODIMP ShellExtension::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID)
{
// Implementação do Initialize
m_cRef = 1; // Inicialize o contador de referências aqui
return S_OK;
}
#define IDI_MYICON 101 // Certifique-se de que este número corresponde ao do arquivo de recursos
#define IDM_DISPLAY 0
STDMETHODIMP ShellExtension::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
if (uFlags & CMF_DEFAULTONLY)
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
// Define o ícone a ser usado
HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
// Exemplo de uso de ReportEvent para registrar um evento
if (g_hEventSource)
{
LPCWSTR pInsertStrings[1] = { TEXT("Tentando adicionar item.") };
ReportEvent(g_hEventSource,
EVENTLOG_INFORMATION_TYPE, // Tipo de evento
0, // Categoria do evento
1, // ID do evento, você deve definir isso em um arquivo de mensagem
NULL, // SID do usuário
1, // Número de strings de inserção
0, // Tamanho dos dados binários
pInsertStrings, // Array de strings de inserção
NULL); // Dados binários
}
InsertMenu(hmenu,
indexMenu,
MF_STRING | MF_BYPOSITION,
idCmdFirst + IDM_DISPLAY,
_T("&Display File Name"));
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(1)); // Indica que adicionamos um item ao menu
}
STDMETHODIMP ShellExtension::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
if (!HIWORD(pici->lpVerb))
{
if (LOWORD(pici->lpVerb) == 0) // O primeiro comando (idCmdFirst)
{
MessageBox(NULL, TEXT("Item de menu clicado!"), TEXT("Aviso"), MB_OK);
}
}
return S_OK;
}
STDMETHODIMP ShellExtension::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pReserved, LPSTR pszName, UINT cchMax)
{
return E_NOTIMPL;
}
STDAPI DllRegisterServer(void)
{
HKEY hKey;
LONG lRes;
// Registra a fonte de eventos
lRes = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" NomeDaExtensao), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
if (lRes == ERROR_SUCCESS)
{
TCHAR szPath[MAX_PATH];
GetModuleFileName(GetModuleHandle(NULL), szPath, MAX_PATH);
// Define o caminho para o arquivo de mensagem (pode ser o próprio módulo, mas normalmente você teria um arquivo de mensagem separado)
RegSetValueEx(hKey, TEXT("EventMessageFile"), 0, REG_SZ, (BYTE*)szPath, (lstrlen(szPath) + 1) * sizeof(TCHAR));
// Define o tipo de arquivo de mensagem
DWORD dwSupport = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
RegSetValueEx(hKey, TEXT("TypesSupported"), 0, REG_DWORD, (BYTE*)&dwSupport, sizeof(DWORD));
RegCloseKey(hKey);
}
else
{
// Trate o erro de registro
return SELFREG_E_CLASS;
}
// Cria a chave CLSID para a classe
lRes = RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID\\" MYUUID), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
if (lRes != ERROR_SUCCESS) return SELFREG_E_CLASS;
// Define o nome da classe
RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE*)TEXT(Title), sizeof(TEXT(Title)));
// Adiciona a entrada para o InprocServer32
HKEY hSubKey;
lRes = RegCreateKeyEx(hKey, TEXT("InprocServer32"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, NULL);
if (lRes == ERROR_SUCCESS)
{
// Caminho completo para a DLL
TCHAR szModule[MAX_PATH];
GetModuleFileName(GetModuleHandle(NULL), szModule, MAX_PATH);
RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE*)szModule, (lstrlen(szModule) + 1) * sizeof(TCHAR));
RegSetValueEx(hSubKey, TEXT("ThreadingModel"), 0, REG_SZ, (BYTE*)TEXT("Apartment"), sizeof(TEXT("Apartment")));
RegCloseKey(hSubKey);
}
// Adicionar a extensão de shell ao menu "Enviar para"
lRes = RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("AllFileSystemObjects\\shellex\\ContextMenuHandlers\\" NomeDaExtensao), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, NULL);
if (lRes == ERROR_SUCCESS)
{
RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE*)TEXT(MYUUID), sizeof(TEXT(MYUUID)));
RegCloseKey(hSubKey);
}
RegCloseKey(hKey);
return lRes == ERROR_SUCCESS ? S_OK : SELFREG_E_CLASS;
}
STDAPI DllUnregisterServer(void)
{
RegDeleteKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" NomeDaExtensao));
// Remover as entradas de registro correspondentes
RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("AllFileSystemObjects\\shellex\\ContextMenuHandlers\\" NomeDaExtensao));
RegDeleteTree(HKEY_CLASSES_ROOT, TEXT("CLSID\\" MYUUID));
return S_OK;
}
// DllMain - ponto de entrada para a DLL
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hEventSource = RegisterEventSource(NULL, TEXT(NomeDaExtensao));
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
if (g_hEventSource)
{
DeregisterEventSource(g_hEventSource);
g_hEventSource = NULL;
}
break;
}
return TRUE;
}
config.def
LIBRARY "ShellExtensionCpp"
EXPORTS
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
Подробнее здесь: https://stackoverflow.com/questions/792 ... n-visual-c
Устранение неполадок контекстного меню в Visual C++ ⇐ C++
Программы на C++. Форум разработчиков
-
Anonymous
1734034538
Anonymous
Я пытался создать программу Visual C++, которая отображает пункт меню, когда пользователь щелкает правой кнопкой мыши, следуя нескольким онлайн-руководствам. Однако, несмотря на регистрацию DLL и перезапуск Проводника Windows, он вообще не работает. Непонятно, чего мне здесь не хватает.
regsvr32.exe ShellExtension.dll тоже работает без проблем.
ShellExtension.h
#pragma once
#include
#include
#include
#include // Adicione isso
#define MYUUID "{6f81fd22-1c80-4619-a401-22d66dc3410b}"
#define NomeDaExtensao "ShellExtension"
#define Title "Shell Extension"
class __declspec(uuid(MYUUID)) ShellExtension : public IShellExtInit, public IContextMenu
{
public:
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IShellExtInit
STDMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID);
// IContextMenu
STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pReserved, LPSTR pszName, UINT cchMax);
private:
ULONG m_cRef;
};
ShellExtension.cpp
#include
#include
#include "ShellExtension.h"
#include "resource.h"
HANDLE g_hEventSource = NULL;
STDMETHODIMP ShellExtension::QueryInterface(REFIID riid, void** ppvObject)
{
if (riid == IID_IUnknown || riid == IID_IShellExtInit || riid == IID_IContextMenu)
{
*ppvObject = this;
AddRef();
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) ShellExtension::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) ShellExtension::Release()
{
ULONG cRef = InterlockedDecrement(&m_cRef);
if (cRef == 0)
delete this;
return cRef;
}
STDMETHODIMP ShellExtension::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID)
{
// Implementação do Initialize
m_cRef = 1; // Inicialize o contador de referências aqui
return S_OK;
}
#define IDI_MYICON 101 // Certifique-se de que este número corresponde ao do arquivo de recursos
#define IDM_DISPLAY 0
STDMETHODIMP ShellExtension::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
if (uFlags & CMF_DEFAULTONLY)
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
// Define o ícone a ser usado
HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
// Exemplo de uso de ReportEvent para registrar um evento
if (g_hEventSource)
{
LPCWSTR pInsertStrings[1] = { TEXT("Tentando adicionar item.") };
ReportEvent(g_hEventSource,
EVENTLOG_INFORMATION_TYPE, // Tipo de evento
0, // Categoria do evento
1, // ID do evento, você deve definir isso em um arquivo de mensagem
NULL, // SID do usuário
1, // Número de strings de inserção
0, // Tamanho dos dados binários
pInsertStrings, // Array de strings de inserção
NULL); // Dados binários
}
InsertMenu(hmenu,
indexMenu,
MF_STRING | MF_BYPOSITION,
idCmdFirst + IDM_DISPLAY,
_T("&Display File Name"));
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(1)); // Indica que adicionamos um item ao menu
}
STDMETHODIMP ShellExtension::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
if (!HIWORD(pici->lpVerb))
{
if (LOWORD(pici->lpVerb) == 0) // O primeiro comando (idCmdFirst)
{
MessageBox(NULL, TEXT("Item de menu clicado!"), TEXT("Aviso"), MB_OK);
}
}
return S_OK;
}
STDMETHODIMP ShellExtension::GetCommandString(UINT_PTR idCmd, UINT uType, UINT* pReserved, LPSTR pszName, UINT cchMax)
{
return E_NOTIMPL;
}
STDAPI DllRegisterServer(void)
{
HKEY hKey;
LONG lRes;
// Registra a fonte de eventos
lRes = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" NomeDaExtensao), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
if (lRes == ERROR_SUCCESS)
{
TCHAR szPath[MAX_PATH];
GetModuleFileName(GetModuleHandle(NULL), szPath, MAX_PATH);
// Define o caminho para o arquivo de mensagem (pode ser o próprio módulo, mas normalmente você teria um arquivo de mensagem separado)
RegSetValueEx(hKey, TEXT("EventMessageFile"), 0, REG_SZ, (BYTE*)szPath, (lstrlen(szPath) + 1) * sizeof(TCHAR));
// Define o tipo de arquivo de mensagem
DWORD dwSupport = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
RegSetValueEx(hKey, TEXT("TypesSupported"), 0, REG_DWORD, (BYTE*)&dwSupport, sizeof(DWORD));
RegCloseKey(hKey);
}
else
{
// Trate o erro de registro
return SELFREG_E_CLASS;
}
// Cria a chave CLSID para a classe
lRes = RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID\\" MYUUID), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
if (lRes != ERROR_SUCCESS) return SELFREG_E_CLASS;
// Define o nome da classe
RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE*)TEXT(Title), sizeof(TEXT(Title)));
// Adiciona a entrada para o InprocServer32
HKEY hSubKey;
lRes = RegCreateKeyEx(hKey, TEXT("InprocServer32"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, NULL);
if (lRes == ERROR_SUCCESS)
{
// Caminho completo para a DLL
TCHAR szModule[MAX_PATH];
GetModuleFileName(GetModuleHandle(NULL), szModule, MAX_PATH);
RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE*)szModule, (lstrlen(szModule) + 1) * sizeof(TCHAR));
RegSetValueEx(hSubKey, TEXT("ThreadingModel"), 0, REG_SZ, (BYTE*)TEXT("Apartment"), sizeof(TEXT("Apartment")));
RegCloseKey(hSubKey);
}
// Adicionar a extensão de shell ao menu "Enviar para"
lRes = RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("AllFileSystemObjects\\shellex\\ContextMenuHandlers\\" NomeDaExtensao), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, NULL);
if (lRes == ERROR_SUCCESS)
{
RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (BYTE*)TEXT(MYUUID), sizeof(TEXT(MYUUID)));
RegCloseKey(hSubKey);
}
RegCloseKey(hKey);
return lRes == ERROR_SUCCESS ? S_OK : SELFREG_E_CLASS;
}
STDAPI DllUnregisterServer(void)
{
RegDeleteKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" NomeDaExtensao));
// Remover as entradas de registro correspondentes
RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("AllFileSystemObjects\\shellex\\ContextMenuHandlers\\" NomeDaExtensao));
RegDeleteTree(HKEY_CLASSES_ROOT, TEXT("CLSID\\" MYUUID));
return S_OK;
}
// DllMain - ponto de entrada para a DLL
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hEventSource = RegisterEventSource(NULL, TEXT(NomeDaExtensao));
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
if (g_hEventSource)
{
DeregisterEventSource(g_hEventSource);
g_hEventSource = NULL;
}
break;
}
return TRUE;
}
config.def
LIBRARY "ShellExtensionCpp"
EXPORTS
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
Подробнее здесь: [url]https://stackoverflow.com/questions/79275065/troubleshooting-right-click-menu-in-visual-c[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия