「C言語/C++/ContextMenu」の編集履歴(バックアップ)一覧はこちら

C言語/C++/ContextMenu」(2012/09/01 (土) 16:44:11) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|aaa| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト| レジストリへの登録 regsvr32 C:\aaa.dll レジストリの登録を解除 regsvr32 /u C:\aaa.dll DLLの置き換え -レジストリの登録を解除 -シェル(explorer)を再起動 デバッグにはDebugViewを使う。 参考 :[[ショートカットメニュー ハンドラ>http://eternalwindows.jp/shell/shellex/shellex08.html]]| aaa.def #highlight(c){{ ; リンカー/入力/モジュール定義ファイル LIBRARY "aaa" EXPORTS DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE DllRegisterServer PRIVATE DllUnregisterServer PRIVATE }} aaa.h #highlight(c){{ class CContextMenu : public IContextMenu, public IShellExtInit { public: STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); // IContextMenu STDMETHODIMP QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); STDMETHODIMP GetCommandString( UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax); STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici); // IShellExtInit STDMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID); CContextMenu(); ~CContextMenu(); private: LONG m_cRef; }; class CClassFactory : public IClassFactory { public: STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); // IClassFactory STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject); STDMETHODIMP LockServer(BOOL fLock); }; }} aaa.cpp #highlight(c){{ #pragma comment(lib, "shlwapi.lib") #include <ShlObj.h> #include <Shlwapi.h> #include <Windows.h> #include "aaa.h" // 関数プロトタイプ宣言 void LockModule(BOOL bLock); BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData); void Trace(LPCTSTR ptcFormat, ...); // グローバル変数 const CLSID CLSID_ContextMenuSample = {0x6986c66a, 0x401f, 0x4535, {0x89, 0x18, 0x48, 0x07, 0x29, 0x39, 0xd2, 0xa4}}; const TCHAR g_szClsid[] = TEXT("{6986C66A-401F-4535-8918-48072939D2A4}"); const TCHAR g_szProgid[] = TEXT("Sample.ShellExtension"); const TCHAR g_szExt[] = TEXT(".aaa"); const TCHAR g_szHandlerName[] = TEXT("My ShortcutMenu Handler"); LONG g_lLocks = 0; HINSTANCE g_hinstDll = NULL; //============================================================================== // CContextMenu CContextMenu::CContextMenu() { m_cRef = 1; LockModule(TRUE); } CContextMenu::~CContextMenu() { LockModule(FALSE); } STDMETHODIMP CContextMenu::QueryInterface(REFIID riid, void **ppvObject) { *ppvObject = NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IContextMenu)) { *ppvObject = static_cast<IContextMenu *>(this); } else if (IsEqualIID(riid, IID_IPersist) || IsEqualIID(riid, IID_IShellExtInit)) { *ppvObject = static_cast<IShellExtInit *>(this); } else { return E_NOINTERFACE; } AddRef(); return S_OK; } STDMETHODIMP_(ULONG) CContextMenu::AddRef() { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CContextMenu::Release() { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return m_cRef; } //------------------------------------------------------------------------------ // IContextMenu STDMETHODIMP CContextMenu::QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { MENUITEMINFO mii; if (uFlags & CMF_DEFAULTONLY) { return MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 0); } mii.cbSize = sizeof (MENUITEMINFO); mii.fMask = MIIM_ID | MIIM_TYPE; mii.fType = MFT_STRING; mii.wID = idCmdFirst; mii.dwTypeData = TEXT("A"); InsertMenuItem(hmenu, indexMenu, TRUE, &mii); return MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1); } STDMETHODIMP CContextMenu::GetCommandString( UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax) { switch (idCmd) { case 0: switch (uFlags) { case GCS_HELPTEXTA: lstrcpyA(pszName, "説明文A"); break; case GCS_HELPTEXTW: lstrcpyW((LPWSTR)pszName, L"説明文A"); break; case GCS_VERBA: lstrcpyA(pszName, "A"); break; case GCS_VERBW: lstrcpyW((LPWSTR)pszName, L"A"); break; } break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici) { UINT idCmd = LOWORD(pici->lpVerb); if (HIWORD(pici->lpVerb) != 0) { return E_INVALIDARG; } switch (idCmd) { case 0: MessageBox(NULL, TEXT("A"), TEXT("OK"), MB_OK); break; } return S_OK; } //------------------------------------------------------------------------------ // IShellExtInit STDMETHODIMP CContextMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID) { Trace(L"Initialize\n"); // Trace(L"%u\n", pidlFolder->mkid.cb); return S_OK; } //============================================================================== // CClassFactory STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObject) { *ppvObject = NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) { *ppvObject = static_cast<IClassFactory *>(this); } else { return E_NOINTERFACE; } AddRef(); return S_OK; } STDMETHODIMP_(ULONG) CClassFactory::AddRef() { LockModule(TRUE); return 2; } STDMETHODIMP_(ULONG) CClassFactory::Release() { LockModule(FALSE); return 1; } //------------------------------------------------------------------------------ // IClassFactory STDMETHODIMP CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) { CContextMenu *p; HRESULT hr; *ppvObject = NULL; if (pUnkOuter != NULL) { return CLASS_E_NOAGGREGATION; } p = new CContextMenu(); if (p == NULL) { return E_OUTOFMEMORY; } hr = p->QueryInterface(riid, ppvObject); p->Release(); return hr; } STDMETHODIMP CClassFactory::LockServer(BOOL fLock) { LockModule(fLock); return S_OK; } //============================================================================== // DLL Export STDAPI DllCanUnloadNow(void) { return (g_lLocks == 0) ? S_OK : S_FALSE; } STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { static CClassFactory serverFactory; HRESULT hr; *ppv = NULL; if (IsEqualCLSID(rclsid, CLSID_ContextMenuSample)) { hr = serverFactory.QueryInterface(riid, ppv); } else { hr = CLASS_E_CLASSNOTAVAILABLE; } return hr; } STDAPI DllRegisterServer(void) { TCHAR szModulePath[MAX_PATH]; TCHAR szKey[256]; wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid); if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("ShellExtension Sample"))) { return E_FAIL; } GetModuleFileName(g_hinstDll, szModulePath, _countof(szModulePath)); wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid); if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, szModulePath)) { return E_FAIL; } wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid); if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, TEXT("ThreadingModel"), TEXT("Apartment"))) { return E_FAIL; } wsprintf(szKey, TEXT("%s"), g_szExt); if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, (LPTSTR)g_szProgid)) { return E_FAIL; } wsprintf(szKey, TEXT("%s\\shellex\\ContextMenuHandlers\\%s"), g_szProgid, g_szHandlerName); if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, (LPTSTR)g_szClsid)) { return E_FAIL; } return S_OK; } STDAPI DllUnregisterServer(void) { TCHAR szKey[256]; wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid); SHDeleteKey(HKEY_CLASSES_ROOT, szKey); SHDeleteKey(HKEY_CLASSES_ROOT, g_szExt); SHDeleteKey(HKEY_CLASSES_ROOT, g_szProgid); return S_OK; } BOOL APIENTRY DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: g_hinstDll = hinstDLL; DisableThreadLibraryCalls(hinstDLL); break; } return TRUE; } //============================================================================== // Function void LockModule(BOOL bLock) { if (bLock) { InterlockedIncrement(&g_lLocks); } else { InterlockedDecrement(&g_lLocks); } } BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData) { HKEY hKey; LONG lResult; DWORD dwSize; lResult = RegCreateKeyEx(hKeyRoot, lpszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); if (lResult != ERROR_SUCCESS) { return FALSE; } if (lpszData != NULL) { dwSize = (lstrlen(lpszData) + 1) * sizeof (TCHAR); } else { dwSize = 0; } RegSetValueEx(hKey, lpszValue, 0, REG_SZ, (LPBYTE)lpszData, dwSize); RegCloseKey(hKey); return TRUE; } void Trace(LPCTSTR ptcFormat, ...) { va_list args; TCHAR atcBuf[512]; int iRet; va_start(args, ptcFormat); iRet = wsprintf(atcBuf, ptcFormat, args); if (0 < iRet) { OutputDebugString(atcBuf); } va_end(args); } }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: