Устранение неполадок контекстного меню в Visual C++C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Устранение неполадок контекстного меню в Visual C++

Сообщение 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


Подробнее здесь: https://stackoverflow.com/questions/792 ... n-visual-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»