الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Shell Extension Contextmenuhandlers

بدأه Moudey في 9 أكتوبر 2008 · 2 رد · 1,329 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم,

هذا مثال بسيط يوضح كيفية إضافة عنصر القائمة "Menu item"

إلى قائمة مستعرض الويندو عند الضغط كلك يمين على الملفات والمجلدات او فى خلفية المجلد.

post-22527-1223502454_thumb.jpg

// ShellExt.cpp
#include <windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlstr.h>
#include <shlobj.h>
#include <initguid.h>
#include <vector>
#include <string>

using namespace std;

// {E184F749-97E8-47be-A72D-14612D18612C}
DEFINE_GUID(CLSID_ShellExt, 0xe184f749, 0x97e8, 0x47be, 0xa7, 0x2d, 0x14, 0x61, 0x2d, 0x18, 0x61, 0x2c);

#define regCLSID 					_T("{E184F749-97E8-47be-A72D-14612D18612C}")
#define regFiles					_T("*\\shellex\\ContextMenuHandlers\\")
#define regFolder					_T("Folder\\shellex\\ContextMenuHandlers\\")
#define regDirectory				_T("Directory\\shellex\\ContextMenuHandlers\\")
#define regDirectory_Background		_T("Directory\\Background\\shellex\\ContextMenuHandlers\\")
#define regAllFilesystemObjects		_T("AllFilesystemObjects\\shellex\\ContextMenuHandlers\\")
#define regShellExt_Approved		_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved\\")

// this is the actual OLE Shell extension handler
class ATL_NO_VTABLE CShellExt :	// Implementation
	public CComObjectRoot,
	public CComCoClass<CShellExt, &CLSID_ShellExt>,
	public IShellExtInit,
	public IContextMenu
{
	private:
		vector<LPSTR>	selectedItems;

	public :
		DECLARE_NO_REGISTRY()
		DECLARE_NOT_AGGREGATABLE(CShellExt)

		BEGIN_COM_MAP(CShellExt)
			COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, 	IShellExtInit)
			COM_INTERFACE_ENTRY_IID(IID_IContextMenu, 	IContextMenu)
		END_COM_MAP()

		// IShellExtInit methods
		STDMETHODIMP Initialize(	LPCITEMIDLIST pidlFolder, 
								 	LPDATAOBJECT pDataObj, 
								 	HKEY hRegKey)
		{
			HRESULT hr = S_OK;
			char *path = new char[MAX_PATH];
			// If Initialize has already been called.
			if(pidlFolder) {
				if(SHGetPathFromIDList(pidlFolder, path)) {
					selectedItems.push_back(path);
					if(path) delete[] path;
					return S_OK;
				} 
				return E_INVALIDARG;
			} else if(pDataObj) {
				// Get the file name from the CF_HDROP.
				FORMATETC fmt = { CF_HDROP, (DVTARGETDEVICE FAR *)NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
				STGMEDIUM stg = { TYMED_HGLOBAL };
				if(SUCCEEDED(pDataObj->GetData(&fmt, &stg)) && stg.hGlobal) {
					// Get a pointer to the actual data.
					HDROP hDrop = (HDROP) GlobalLock(stg.hGlobal);
					// Make sure it worked.
					if(SUCCEEDED(hDrop)) {
						// Get the count of files the user has selected...
						UINT filesCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
						for(UINT i = 0; i < filesCount; ++i) {
							if(path) delete[] path;
							path = new char[MAX_PATH];
							DragQueryFile( hDrop, i, path, MAX_PATH);
							selectedItems.push_back(path);
						}
					}
					hr = S_OK;
				} else
					hr = E_INVALIDARG;

				if (stg.hGlobal) {
					GlobalUnlock(stg.hGlobal);
					ReleaseStgMedium(&stg);
					if(path) delete[] path;
				}
			} else 
				hr = E_INVALIDARG;	
			return hr;
		}

		// IContextMenu members
		STDMETHODIMP QueryContextMenu(	HMENU hMenu,
									   	UINT indexMenu, 
										UINT idCmdFirst, 
										UINT idCmdLast, 
										UINT uFlags)
		{
			// If the flags include CMF_DEFAULTONLY then we shouldn't do anything.
			if ( uFlags & CMF_DEFAULTONLY )
				return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);

			TCHAR menuTitle[MAX_PATH];

			// Check if we already added our menu entry.
			int count = GetMenuItemCount(hMenu);
			for(int i = 0; i < count; ++i)
			{
				if(GetMenuString(hMenu, i, menuTitle, MAX_PATH, MF_BYPOSITION)) {
					if(_stricmp(menuTitle, _T("Test ShellExt")) == 0)
						return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
				}
			}
			if(InsertMenu(hMenu, indexMenu, MF_BYPOSITION | MF_HILITE, idCmdFirst, _T("Test ShellExt"))) {
				// Tell the shell we added 1 top-level menu item.
				return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 1);
			}
			return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
		}
		// IContextMenu members
		STDMETHODIMP GetCommandString(	UINT idCmd, 
										UINT uFlags, 
										UINT FAR*, 
										LPSTR pszName, 
										UINT cchMax)
		{
			USES_CONVERSION;
			// Check idCmd, it must be 0 since we have only one menu item.
			if (idCmd > 0) return E_INVALIDARG;
			// If Explorer is asking for a help string, copy our string into the supplied buffer.
			if ( uFlags & GCS_HELPTEXT ) {
				LPCTSTR pszText = _T("Test Shell Extension.");	   
				if ( uFlags & GCS_UNICODE ) {
					// We need to cast pszName to a Unicode string, and then use the Unicode string copy API.
					lstrcpynW ((LPWSTR) pszName, T2CW(pszText), cchMax);
					return S_OK;
				} else {
					// Use the ANSI string copy API to return the help string.
					lstrcpynA (pszName, T2CA(pszText), cchMax);
					return S_OK;
				}
			}
			return E_INVALIDARG;
		}
		// IContextMenu members
		STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
		{
			CString files;
			for(UINT i = 0; i < selectedItems.size(); i++) {
				files.AppendFormat("%s\n", selectedItems);
			}

			if(0 == HIWORD(lpcmi->lpVerb)) { //if called by command id
				WORD idCmd = LOWORD(lpcmi->lpVerb);
				// The command ID must be 0 since we only have one menu item.
				if(idCmd == 0) {
					MessageBox(0, files, "InvokeCommand by ID", 0);
					return S_OK;
				}
			} else { //if called by verb
				if( 0 == strcmp("Test ShellExt", lpcmi->lpVerb) ) {
					MessageBox(0, files, "InvokeCommand by verb", 0);
					return S_OK;
				}
			}
			return E_INVALIDARG;
		}
};

BEGIN_OBJECT_MAP(ObjectMap)
	OBJECT_ENTRY(CLSID_ShellExt, CShellExt)
END_OBJECT_MAP()

CComModule module;
// DLL Entry Point
extern "C" BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
	if( dwReason == DLL_PROCESS_ATTACH ) {
		module.Init(ObjectMap, hInstance);
		DisableThreadLibraryCalls(hInstance);
	} else if(dwReason == DLL_PROCESS_DETACH)
		module.Term();
	return TRUE;
}

// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow()
{
	return module.GetLockCount() ? S_FALSE : S_OK;
}

// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppvOut)
{
	return module.GetClassObject(rclsid, riid, ppvOut);
}

// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer()
{
	CRegKey key;
	char *dllPath = new char[MAX_PATH];
	GetModuleFileName(module.GetModuleInstance(), dllPath, MAX_PATH);

	if(key.Open(HKEY_CLASSES_ROOT, _T("CLSID\\")) == ERROR_SUCCESS) {
		key.SetKeyValue(regCLSID _T("\\InprocServer32"), dllPath);
		key.SetKeyValue(regCLSID _T("\\InprocServer32"), _T("Apartment"), _T("ThreadingModel"));
	}

	if(key.Open(
		HKEY_CLASSES_ROOT, regFiles) == ERROR_SUCCESS) {
		key.SetKeyValue(_T("TestShellExt"), regCLSID);
	}
	if(key.Open(
		HKEY_CLASSES_ROOT, regDirectory) == ERROR_SUCCESS) {
		key.SetKeyValue(_T("TestShellExt"), regCLSID);
	}
	if(key.Open(
		HKEY_CLASSES_ROOT, regDirectory_Background) == ERROR_SUCCESS) {
		key.SetKeyValue(_T("TestShellExt"), regCLSID);
	}
	if(key.Open(
		HKEY_CLASSES_ROOT, regFolder) == ERROR_SUCCESS) {
		key.SetKeyValue(_T("TestShellExt"), regCLSID);
	}
	if(key.Open(
		HKEY_CLASSES_ROOT, regAllFilesystemObjects) == ERROR_SUCCESS) {
		key.SetKeyValue(_T("TestShellExt"), regCLSID);
	}
	if(key.Open(
		HKEY_LOCAL_MACHINE, regShellExt_Approved) == ERROR_SUCCESS) {
		key.SetStringValue(regCLSID, _T("Test ShellExtension"));
	}
	key.Close();
	if(dllPath) delete[] dllPath;
	return module.RegisterServer(FALSE);
}

// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer()
{
	CRegKey key;
	if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID\\")) == ERROR_SUCCESS) {
		key.DeleteSubKey(regCLSID);
	}
	if (key.Open(HKEY_CLASSES_ROOT, regFiles) == ERROR_SUCCESS) {
		key.DeleteSubKey(_T("TestShellExt"));
	}
	if (key.Open(HKEY_CLASSES_ROOT, regDirectory) == ERROR_SUCCESS) {
		key.DeleteSubKey(_T("TestShellExt"));
	}
	if (key.Open(HKEY_CLASSES_ROOT, regDirectory_Background) == ERROR_SUCCESS) {
		key.DeleteSubKey(_T("TestShellExt"));
	}
	if (key.Open(HKEY_CLASSES_ROOT, regFolder) == ERROR_SUCCESS) {
		key.DeleteSubKey(_T("TestShellExt"));
	}
	if (key.Open(HKEY_CLASSES_ROOT, regAllFilesystemObjects) == ERROR_SUCCESS) {
		key.DeleteSubKey(_T("TestShellExt"));
	}
	if(key.Open(HKEY_LOCAL_MACHINE, regShellExt_Approved) == ERROR_SUCCESS) {
		key.DeleteValue(regCLSID);
	}
	key.Close();
	return module.UnregisterServer(FALSE);
}

للمزيد ...

Add Item To Explorer Context Menu

كيف اقوم بعمل shell تضاف الي ال registry عن طريق ملف dll

ShellExt.zip

تم تعديل هذه المشاركة بواسطة Moudey في 9 أكتوبر 2008 في 01:12

مواضيع متنوعة

#2

السلام عليكــم ورحمـة الله وبركاتــه ،،

up :)

#3

وعليكــم السـلام ورحمة الله وبركاتـه..

ممتاز ، UP في وقته ا أخي بن العيد ،،

كنت أريد عمل ذلك وكتبت القطعه :

#define HKCR HKEY_CLASSES_ROOT
#define CONTEXT TEXT("Folder\\shell")

VOID ResettingRegistry::  AddToContextMenu() {
	//***** Get The Path and Name of Current Application
	HMODULE hModule = GetModuleHandle(NULL);
	TCHAR ModulePath[MAX_PATH];
	GetModuleFileName(hModule,ModulePath,sizeof(ModulePath));
	lstrcat(ModulePath,TEXT(" \"%1\" ") );

	//***** Make new Subkey At context Subkey in Registry
	HKEY hNewKey;
	TCHAR lpSubKey[MAX_PATH]; 
	lstrcpy(lpSubKey,CONTEXT);
	lstrcat(lpSubKey,TEXT("\\MyProgram\\command"));

	DWORD Result;
	RegCreateKeyEx(HKCR,lpSubKey,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hNewKey,&Result);

	//***** Inserting Value At This new subkey
	RegSetValueEx(hNewKey,TEXT(""),0,REG_SZ,(BYTE*)ModulePath,sizeof(ModulePath));

	//***** Close HKey
	RegCloseKey(hNewKey);
}

ولكنها تعمل على المجلدات فقط ،، ولعمل على الجميع قرأت يجب التعامل atl وكنسلت الفكره حينها :) ..

الأن سأستخدم هذا أفضل بالتأكيد ،،وان شاء الله تعمل على GCC .

جزاكم الله خيرا ، كاتب الموضوع ورافع الموضوع وقارئ الموضوع :) .

بالتوفيق ،

تم تعديل هذه المشاركة بواسطة Wajdy Essam في 22 يوليو 2009 في 02:28 — السبب: add #define

http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة

https://moalfat.com  للكتب الالكترونية والكورسات التعليمية

Everything we see now is just an engineering solution based on old science

مواضيع مشابهة