Расширение оболочки windows мастер сом объектов

Собственное расширение оболочки Windows C++ Builder Решение и ответ на вопрос 215143

Задача строится из двух частей:

1. Написать и отладить программу в оболочке Windows, обрабатывающую контекстное меню (контекстное меню представляет собой список пунктов, отображающийся при щелчке правой кнопкой мыши на файл).
2. Написать и отладить программу в оболочке Windows, отображающую истинный размер файла.

/*
1. Задача по созданию расширения оболочки включает в себя две части: оболочка (Shell) и расширение (extension) — код, который требуется написать, чтобы получить управление проводником в определенный момент (например, при щелчке правой кнопкой мышки на файле определённого типа). Таким образом, расширение оболочки — это COM объект, который добавляет некоторые особенности к проводнику.

Windows API предоставляет базовые функции, позволяющие использовать COM-объекты. Библиотеки MFC и, особенно, ATL/WTL предоставляют гораздо более гибкие и удобные средства для работы с COM.
Для обработки контекстного меню можно создать COM-сервер в своём проекте и 1 COM-объект, который будет через сервер заниматься непосредственно обработкой меню. В Microsoft Visual Studio 2010, например, самое удобное средство для этого – мастер создания ATL-проекта.

*/
ТО что в коментах это как подсказка, с чего начинать…. А я кажется всё равно в затруднение…О_о
Может, кто может подсказать что да как?))

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

01.01.2007

С каждой новой версией Windows, её оболочка (shell) приобретает всё больше и больше различных возможностей. Обычно эти возможности добавляются через расширения оболочки, которые позволяют разработчикам добавлять различные возможности в существующую оболочку Windows. Вот некоторые примеры расширений оболочки: Context Menus (меню, зависящее от объекта, на котором кликнули правой кнопкой мыши), Property Sheet Handlers (страницы в виде закладок, которые появляются в случае выбора пункта контексного меню Properties), Folder Customization, и т.д.

На сайте Microsoft доступно большое количество информации о расширениях оболочки, но эта информация мало полезна Delphi аудитории. Итак давайте рассмотрим расширение оболочки под названием «Всплывающие подсказки» (InfoTip), которые появляются в эксплорере, при наведении мышкой на файл.

Расширения оболочки – Краткий обзор

Расширения оболочки существуют в виде In Process COM серверов. В ответ на определённые события оболочки проводник вызывает соответствующее расширение. Проводник очень специфически реагирует на различные функции в пределах оболочки. Первое, что делает Проводник — это проверяет модули, которые были зарегистрированы для определённого события и, если таковой существует, то загружает данный модуль.

Чтобы быть расширением оболочки, COM сервер должен включать в себя интерфейс, который определяет специфическое поведение для данного расширения, а так же он должен включать в себя интефейс инициализации. Наконец, чтобы быть расширением оболочки, COM сервер должен следовать определённым в системе методам регистрации.

Следующая таблица представляет собой список всех существующих на сегодняшний день расширений оболочки, а так же их минимальных версий, учавствующих интерфейсов и их описаний:

Тип Добавлено в Версия Используемые интерфейсы Описание
Context Menu File class and shell’s object Windows 95+ IContextMenu, IContextMenu2, или IContextMenu3 Позволяет добавлять новые пункты в контекстное меню объекта оболочки.
Right Drag and Drop File class and shell’s object Windows 95+ IContextMenu, IContextMenu2, или IContextMenu3 Позволяет добавлять новые пункты в контекстное меню, при перетаскивании правой кнопкой мыши и отпускании файлов.
Drawing Shell Icons File class and shell’s object Windows 95+ IExtractIcon Позволяет решить в данный момент, какая будет отображаться иконка для данного файла.
Property Sheet File class and shell’s object Windows 95+ IShellPropSheetExt Позволяет
добавлять дополнительные страницы
property sheet в диалог свойств файла. Так
же это работает для Панели
управления.
Left Drag and Drop File class and shell’s object Windows 95+ IDropTarget Позволяет решать
— что делать с перетаскиваемым
объектом (используя левую кнопку
мыши) на другой объект в оболочке.
Clipboard File class and shell’s object Windows 95+ IDataObject Позволяет Вам
определить, как объект скопирован и
извлечён из буфера обмена.
File Hook   Windows 95+ ICopyHook Позволяет
контролировать некоторые файловые
операции, которые происходят черех
оболочку. Вы можете разрешить или
запретить их, но Вы не сможете
получать уведомление об успешности
операции или об ошибке.
Program Execution Explorer Desktop Update IShellExecuteHook Позволяет
перехватывать некоторые выполнения
программ, которые происходят через
оболочку.
Infotip File class and shell’s object Desktop Update IQueryInfo Позволяет
отображать короткие текстовые
сообщения, когда курсор мышки
находится на определённом файле.
Column Folders Windows 2000 IColumnProvider Позволяет
добавлять новую колонку в режиме
отображения Details в Проводнике.
Icon Overlay Explorer Windows 2000 IShellIconOverlay Позволяет
определить собственные изображения,
которые будут использоваться как
иконки.
Search Explorer Windows 2000 IContextMenu Позволяет
добавить новую ячейку в меню «Найти»
(в меню, открывающемся при нажатии
на «Пуск»).
Cleanup Cleanup Manager Windows 2000 IEmptyVolumeCache2 Позволяет
добавить новую ячейку в Менеджер
Очистки для восстановления
дискового пространства.
         

Всплывающие подсказки – Введение и обзор

Infotip-ы это всплывающие окна подсказки, которые появляются в случае, если курсор мышки находится над любым файлом. Если расширения для файла не было зарегистрировано, то будет высвечиваться окошко с подсказкой по умолчанию, однако Вы можете создать своё собственно расширение для отображения информации об определённом типе файла. Например, Office 2000 инсталирует обработчики для MS Word и MS Excel, которые отображают Имя, Автора и заголовок из свойств документа. Расширения Infotip отличаются от других расширений оболочки по регистрации. Об этом мы поговорим позже, когда перейдём к регистрации нашего расширения Infotip.

Implementing Infotip Extensions

Расширение Infotip является In-Process (Inproc) COM Server. Это значит, что Infotip является обыкновенной Windows DLL, которая экспортирует необходимые методы, чтобы быть как обыкновенным элементом управления ActiveX. Расширение Infotip так же включает IQueryInfo и IPersistFile и должна самостоятельно регистрировать себя в реестре. В виду того, что IQueryInfo и IPersistFile являются интерфейсами, то они не содержат исходного кода своих методов. Поэтому наш объект включает в себя каждый метод, определённый в обоих интерфейсах; однако, некоторые из методов не являются необходимыми для нашего расширения Infotip, поэтому мы просто возвращаем E_NOTIMPL, чтобы показать, что они не осуществимы.

IQueryInfo обеспечивает отображение текста во всплывающем окошке и содержит два метода: GetInfoFlags – Получает информационные флаги. На текущий момент это метод не используется, поэтому возвращаем E_NOTIMPL. GetInfoTip – Получает текст Infotip-а.

GetInfoTip определена следующим образом:

function GetInfoTip(dwFlags: DWORD; var ppwszTip: PWideChar): HResult; stdcall;

dwFlags

в данный момент не используется

ppwszTip

Адрес указателя на строку Unicode, кото string pointer that receives the tip string pointer.

Важное замечание

Параметр ppwszTip метода GetInfoTip — это указатель на строковый буфер Unicode, который содержит текст, отображаемый в всплывающем информационном поле. Этот буфер должен быть распределен, используя стандартную программу распределения памяти оболочки, потому что буфер распределен нашим приложением, но освобожден оболочкой. Чтобы быть уверенным, что всё пройдёт успешно, используйте SHGetMalloc для получения указателя на программу распределения памяти оболочки — объект IMalloc. Затем используйте метод Alloc из IMalloc-а для распределения необходимой памяти для буфера содержащего Unicode представление текста Infotip.

Исходник содержит стандартный код, который Вы можете использовать для всех расширений Infotip, которые Вы создадите.

IPersistFile это то, при помощи чего оболочка обеспечивает расширение информацией о файле, на котором находится курсор. В интерфейсе определены пять методов:

IsDirty

проверяет объект на предмет изменений, сделанных в текущем файле. Наше расширение не требует данного метода, поэтому возвращаем E_NOTIMPL.

Load

открывает указанный файл и инициализирует объект из содержимого файла. Мы будем использовать этот метод для получения имени файла, на котором находится курсор.

Save

сохраняет объект в указанном файле. Мы его не используем и возвращаем E_NOTIMPL.

SaveCompleted

уведомляет объект, о том, что он может быть переведён из режима NoScribble в режим Normal. Не используем, поэтому возвращаем E_NOTIMPL.

GetCurFile

получает текущее имя файла, связанного с объектом. Тоже возвращаем E_NOTIMPL.

 

Load определена следующим образом:

function Load(pszFileName: PoleStr; dwMode: LongInt): HResult; stdcall;

pszFileName

указатель на строку, содержащую абсолютный путь открываемого файла. Строка должна завершаться нулём.

dwMode

содержит набор атрибутов для открытия файла.

 

Чтобы получить имя файла и его путь, мы будем использовать только IPersistFile; фактически мы не используем интерфейс для доступа к файлу, поэтому игнорируем флаги. Стандартная реализация метода Load сохраняет содержимое pszFileName в приватную переменную, которая будет использоваться в IQueryInfo::GetInfoTip для расположения файла.

Регистрация расширения Infotip

Регистрация происходит в два этапа:

1. При помощи regsvr32.exe регистрируется COM DLL (Пуск (Start)..Выполнить(Run))

regsvr32 «C:…DPRInfoTip.dll»

2. Добавление ссылки на расширение (.dpr) в ключ реестра HKEY_CLASSES_ROOT.

По умолчанию значение для нового ключа должно быть CLSID объекта COM, который содержит расширение оболочки. Данное значение можно получить из файла Type Library, который был сгенерирован Delphi (имя файла оканчивается на «_TLB.pas»). Для нашего примера расширения CLSID назван CLASS_DPRInfoTip и содержит значение «{B20433A8-D083-11D4-993A-00D00912C440}».

Самый простой способ внести изменения в реестр — это сделать копию файла .REG, содержащуюся в исходниках проекта. Просто измените CLSID и расширение файла на необходимые значения.

Одно важное замечание:

Если Вы регистрируете расширение оболочки в Windows NT или 2000, то необходимо войти в систему с правами администратора.

  • Download HelloExtNoAtl.zip — 29.1 KB 

Introduction

A shell extension is just a COM component with specific interfaces of shell. There are many articles on how to write shell extensions with ATL on codeproject. Though ATL is a really nice tool to build a COM object, we have to do it without ATL or MFC, just plain C++. In this way, we can understand how a Shell Extension works in more depth and even build it without commerical libraries from Microsoft.

In this article, the simple shell extension example The Complete Idiot’s Guide to Writing Shell Extensions — Part I  will be rewritten without ATL. Its name is HelloExtNoATL.   

With ATL, most the processes are be done by project or class wizard. We don’t need to write even one line to create the skeleton of Shell Extension project. Only methods for the COM object need be implemented by ourself. 

Without ATL, most the code for the COM object is the same, but IClassFactory and registration have to be done in our own code.  We can create it in follow steps:  

  1. Add a GUID
  2. Implement IClassFactory
  3. Implement CShellExt 
  4. Implement registration functions

Step 1: add a GUID for the COM object

Globally Universal Identifier (GUID) is mandatory for all COM objects. It’s done by class wizard in Visual Studio for ATL. We can use guidgen.exe from Visual Studio or some online guid generator to create one for HelloExtNoATL without the help of Class Wizard.  

DEFINE_GUID(CLSID_HelloExtNoAtl, 0xcbf88fc2, 0xf150, 0x4f29, 0xbc, 0x80, 0xce, 0x30, 0xef, 0xd1, 0xb6, 0x2c);
 
  

Step 2: Implement IClassFactory   

It’s one of major differences of COM objects between plain C++ and ATL. We have to implement our own ClassFactory. In ATL, it can be created automatically by an IDL file.

In CClassFactory, interface IUnknow and IClassFactory need be implemented. So the COM object interface methods can be queried and called. Its instance can be created with method CreateInstance and its ID.

 In constract, ATL has implemented IUnknown by default.  No more code for that. 

#if !defined(AFX_CLASSFACTORY_H__3B4B8B30_5B16_4B69_ACC8_25C7259A9F74__INCLUDED_)
#define AFX_CLASSFACTORY_H__3B4B8B30_5B16_4B69_ACC8_25C7259A9F74__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

extern HINSTANCE  g_hInst;
extern UINT       g_DllRefCount;

class CClassFactory : public IClassFactory  
{
protected:
	DWORD m_ObjRefCount;
public:
	CClassFactory();
	virtual ~CClassFactory();

      STDMETHODIMP QueryInterface(REFIID, LPVOID*);
   STDMETHODIMP_(DWORD) AddRef();
   STDMETHODIMP_(DWORD) Release();

      STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID*);
   STDMETHODIMP LockServer(BOOL) { return E_NOTIMPL; };
};

#endif // !defined(AFX_CLASSFACTORY_H__3B4B8B30_5B16_4B69_ACC8_25C7259A9F74__INCLUDED_) 

 
Most methods is plain and the same for all COM object classes. Method QueryInterface and  CreateInstance should be implemented accordingly for HelloExtNoATL.

In CClassFactory, this pointer is converted to IClassFactory * when the ID equals to IID_IClassFactory.

STDMETHODIMP CClassFactory::QueryInterface( REFIID riid, LPVOID *ppReturn )
{
	*ppReturn = NULL;

	if( IsEqualIID(riid, IID_IUnknown) )
	    *ppReturn = this;
	else 
	    if( IsEqualIID(riid, IID_IClassFactory) )
		*ppReturn = (IClassFactory*)this;


	if( *ppReturn )
	{
		LPUNKNOWN pUnk = (LPUNKNOWN)(*ppReturn);
		pUnk->AddRef();
		return S_OK;
	}

	return E_NOINTERFACE;
} 

In CClassFactory::CreateInstance, the COM object CShellExt is created,  then its Interface pointer is returned by its ID,.

STDMETHODIMP CClassFactory::CreateInstance( LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject )
{
	*ppObject = NULL;
	if( pUnknown != NULL )
		return CLASS_E_NOAGGREGATION;

		CShellExt *pShellExt = new CShellExt();
	if( NULL==pShellExt ) 
		return E_OUTOFMEMORY;

		HRESULT hResult = pShellExt->QueryInterface(riid, ppObject);
	pShellExt->Release();
	return hResult;
}  

Step 3: Implement the COM class

HelloExtNoAtl just extends the context menu of Windows explorer. IShellExtInit and IContextMenu should be implemented in the COM class. 
Since in pure plain C++, CShellExt inherits IShellExtInit and IContextMenu directly. Most code can be copied from the ATL sample directly.

 It also implements IUknown which is common for all COM objects.  In contract, ATL has implemented IUnknown by default. We have to code it ourself for class CShellExt. 

#if !defined(AFX_SHELLEXT_H__38EFB68B_5591_485A_9E50_409E8CDE10E2__INCLUDED_)
#define AFX_SHELLEXT_H__38EFB68B_5591_485A_9E50_409E8CDE10E2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CShellExt : public IShellExtInit, IContextMenu
{
protected:
	DWORD m_ObjRefCount;
public:
	CShellExt();
	virtual ~CShellExt();

		STDMETHOD (QueryInterface) (REFIID riid, LPVOID * ppvObj);
	STDMETHOD_ (ULONG, AddRef) (void);
	STDMETHOD_ (ULONG, Release) (void);
	

        STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);

        STDMETHODIMP GetCommandString(UINT_PTR, UINT, UINT*, LPSTR, UINT);
    STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
    STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT);
protected:
    TCHAR m_szFile [MAX_PATH];
};

#endif // !defined(AFX_SHELLEXT_H__38EFB68B_5591_485A_9E50_409E8CDE10E2__INCLUDED_)

Step 4: Registration

In ATL, a registration script is included in the project. It can be used to register and unregister a shell extension. But with plain C++, we have to implement all the registry operations manually.

Except adding registry entries for common COM objects, extra entries for shell extension also need be created. For HelloExtNoAtl, HKEY_CLASSES_ROOTFolderShellExContextMenuHandlersHelloExtNoAtl is created. Because use it will extend the context menu functions of explorer. As the entry indicates, a menu entry will be appended when the context menu of a folder is popped up. 

#include <windows.h>
#include <shlobj.h>

#include "HelloExtNoAtl.h"

#include "ClassFactory.h"
#include "Utility.h"

#include <olectl.h>

HINSTANCE   g_hInst;
UINT        g_DllRefCount;

#pragma data_seg(".text")
#define INITGUID
#include <initguid.h>
#include <shlguid.h>
#include "Guid.h"
#pragma data_seg()

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
			g_hInst = (HINSTANCE)hModule;
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
			break;
    }
    return TRUE;
}



STDAPI DllCanUnloadNow( VOID )
{
	return (g_DllRefCount ? S_FALSE : S_OK);
}




STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID *ppReturn )
{
	*ppReturn = NULL;

		if( !IsEqualCLSID(rclsid, CLSID_HelloExtNoAtl) )
	   return CLASS_E_CLASSNOTAVAILABLE;
   
		CClassFactory *pClassFactory = new CClassFactory();
	if( pClassFactory==NULL )
	   return E_OUTOFMEMORY;
   
		HRESULT hResult = pClassFactory->QueryInterface(riid, ppReturn);
	pClassFactory->Release();
	return hResult;
}





typedef struct{
   HKEY  hRootKey;
   LPTSTR lpszSubKey;
   LPTSTR lpszValueName;
   LPTSTR lpszData;
}REGSTRUCT, *LPREGSTRUCT;

STDAPI DllRegisterServer( VOID )
{
	INT i;
	HKEY hKey;
	LRESULT lResult;
	DWORD dwDisp;
	TCHAR szSubKey[MAX_PATH];
	TCHAR szCLSID[MAX_PATH];
	TCHAR szModule[MAX_PATH];
	LPWSTR pwsz;

		StringFromIID( CLSID_HelloExtNoAtl, &pwsz );

	if( pwsz )
	{
		WideCharToLocal( szCLSID, pwsz, ARRAYSIZE(szCLSID) );
        LPMALLOC pMalloc;
        CoGetMalloc(1, &pMalloc);
		if( pMalloc )
		{
	      pMalloc->Free(pwsz);
		  pMalloc->Release();
		}
    }

		GetModuleFileName( g_hInst, szModule, ARRAYSIZE(szModule) );

		REGSTRUCT ClsidEntries[] = {  
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s"),                  NULL,                   TEXT("HelloExtNoAtl"),
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s"),                  TEXT("InfoTip"),        TEXT("HelloExtNoAtl."),
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s\InprocServer32"),  NULL,                   TEXT("%s"),
        HKEY_CLASSES_ROOT, TEXT("CLSID\%s\InprocServer32"),  TEXT("ThreadingModel"), TEXT("Apartment"),
        HKEY_CLASSES_ROOT, TEXT("CLSID\%s\DefaultIcon"),     NULL,                   TEXT("%s,0"),
        NULL,              NULL,                               NULL,                   NULL};

	for( i=0; ClsidEntries[i].hRootKey; i++ )
    {
				wsprintf( szSubKey, ClsidEntries[i].lpszSubKey, szCLSID );
        lResult = RegCreateKeyEx(  ClsidEntries[i].hRootKey,
                              szSubKey,
                              0,
                              NULL,
                              REG_OPTION_NON_VOLATILE,
                              KEY_WRITE,
                              NULL,
                              &hKey,
                              &dwDisp );
   
		if( lResult==NOERROR )
		{
			 TCHAR szData[MAX_PATH];
			 wsprintf(szData, ClsidEntries[i].lpszData, szModule);
			 lResult = RegSetValueEx( hKey,
                            ClsidEntries[i].lpszValueName,
                            0,
                            REG_SZ,
                            (LPBYTE)szData,
                            lstrlen(szData) + 1);
      
			 RegCloseKey(hKey);
		}
		else
			return SELFREG_E_CLASS;
    }

		lstrcpy( szSubKey, TEXT("Folder\ShellEx\ContextMenuHandlers\HelloExtNoAtl"));
	lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT,
		szSubKey,
		0,
		NULL,
		REG_OPTION_NON_VOLATILE,
		KEY_WRITE,
		NULL,
		&hKey,
		&dwDisp);

	if( lResult==NOERROR )
	{
		TCHAR szData[MAX_PATH];
		lstrcpy(szData, szCLSID);
		lResult = RegSetValueEx( hKey,
			NULL,
			0,
			REG_SZ,
			(LPBYTE)szData,
			lstrlen(szData) + 1);

		RegCloseKey(hKey);
	}
	else
		return SELFREG_E_CLASS;

      OSVERSIONINFO  osvi;
   osvi.dwOSVersionInfoSize = sizeof(osvi);
   GetVersionEx( &osvi );

   if( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId )
   {
	   lstrcpy( szSubKey, TEXT("Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved"));
	   lResult = RegCreateKeyEx(  HKEY_LOCAL_MACHINE,
                              szSubKey,
                              0,
                              NULL,
                              REG_OPTION_NON_VOLATILE,
                              KEY_WRITE,
                              NULL,
                              &hKey,
                              &dwDisp);

       if( lResult==NOERROR )
       {
		   TCHAR szData[MAX_PATH];
	       lstrcpy(szData, TEXT("HelloExtNoAtl"));
           lResult = RegSetValueEx( hKey,
                                 szCLSID,
                                 0,
                                 REG_SZ,
                                 (LPBYTE)szData,
                                 lstrlen(szData) + 1);
      
	      RegCloseKey(hKey);
      }
	  else
		  return SELFREG_E_CLASS;
   }

   return S_OK;
}



STDAPI DllUnregisterServer( VOID )
{
	INT i;
		LRESULT lResult;
		TCHAR szSubKey[MAX_PATH];
	TCHAR szCLSID[MAX_PATH];
	TCHAR szModule[MAX_PATH];
	LPWSTR pwsz;

		StringFromIID( CLSID_HelloExtNoAtl, &pwsz );

	if( pwsz )
	{
		WideCharToLocal( szCLSID, pwsz, ARRAYSIZE(szCLSID) );
        LPMALLOC pMalloc;
        CoGetMalloc(1, &pMalloc);
		if( pMalloc )
		{
	      pMalloc->Free(pwsz);
		  pMalloc->Release();
		}
    }

		GetModuleFileName( g_hInst, szModule, ARRAYSIZE(szModule) );

		REGSTRUCT ClsidEntries[] = {  
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s"),                  NULL,                   TEXT("HelloExtNoAtl"),
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s"),                  TEXT("InfoTip"),        TEXT("HelloExtNoAtl."),
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s\InprocServer32"),  NULL,                   TEXT("%s"),
        HKEY_CLASSES_ROOT, TEXT("CLSID\%s\InprocServer32"),  TEXT("ThreadingModel"), TEXT("Apartment"),
        HKEY_CLASSES_ROOT, TEXT("CLSID\%s\DefaultIcon"),     NULL,                   TEXT("%s,0"),
        NULL,              NULL,                               NULL,                   NULL};

	for( i=0; ClsidEntries[i].hRootKey; i++ )
        {
				wsprintf( szSubKey, ClsidEntries[i].lpszSubKey, szCLSID );
		lResult = RegDeleteKey(ClsidEntries[i].hRootKey, szSubKey);
        }


		lstrcpy( szSubKey, TEXT("Folder\ShellEx\ContextMenuHandlers\HelloExtNoAtl"));
	lResult = RegDeleteKey(HKEY_CLASSES_ROOT, szSubKey);


      OSVERSIONINFO  osvi;
   osvi.dwOSVersionInfoSize = sizeof(osvi);
   GetVersionEx( &osvi );

   if( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId )
   {
	   lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szSubKey);
   }

	return S_OK;
}   

Installation

The installation step is the same for all COM objects whose standard register/unregister methods are implemented. Just use regsvr32.exe to install or uninstall it.  

What Does It All Look Like?  

 Image 1

Image 2

Conclusion

After reading this article and trying the code, we can find the major difference of building a Shell Extension between ATL and plain C++. You can also read articles about creating COM objects in plain C or C++ on CodeProject.

References

COM-in-plain-C 

The Complete Idiot’s Guide to Writing Shell Extensions — Part I

History

 
October 28, 2013: Article first published.

This member has not yet provided a Biography. Assume it’s interesting and varied, and probably something to do with programming.

  • Download HelloExtNoAtl.zip — 29.1 KB 

Introduction

A shell extension is just a COM component with specific interfaces of shell. There are many articles on how to write shell extensions with ATL on codeproject. Though ATL is a really nice tool to build a COM object, we have to do it without ATL or MFC, just plain C++. In this way, we can understand how a Shell Extension works in more depth and even build it without commerical libraries from Microsoft.

In this article, the simple shell extension example The Complete Idiot’s Guide to Writing Shell Extensions — Part I  will be rewritten without ATL. Its name is HelloExtNoATL.   

With ATL, most the processes are be done by project or class wizard. We don’t need to write even one line to create the skeleton of Shell Extension project. Only methods for the COM object need be implemented by ourself. 

Without ATL, most the code for the COM object is the same, but IClassFactory and registration have to be done in our own code.  We can create it in follow steps:  

  1. Add a GUID
  2. Implement IClassFactory
  3. Implement CShellExt 
  4. Implement registration functions

Step 1: add a GUID for the COM object

Globally Universal Identifier (GUID) is mandatory for all COM objects. It’s done by class wizard in Visual Studio for ATL. We can use guidgen.exe from Visual Studio or some online guid generator to create one for HelloExtNoATL without the help of Class Wizard.  

DEFINE_GUID(CLSID_HelloExtNoAtl, 0xcbf88fc2, 0xf150, 0x4f29, 0xbc, 0x80, 0xce, 0x30, 0xef, 0xd1, 0xb6, 0x2c);
 
  

Step 2: Implement IClassFactory   

It’s one of major differences of COM objects between plain C++ and ATL. We have to implement our own ClassFactory. In ATL, it can be created automatically by an IDL file.

In CClassFactory, interface IUnknow and IClassFactory need be implemented. So the COM object interface methods can be queried and called. Its instance can be created with method CreateInstance and its ID.

 In constract, ATL has implemented IUnknown by default.  No more code for that. 

#if !defined(AFX_CLASSFACTORY_H__3B4B8B30_5B16_4B69_ACC8_25C7259A9F74__INCLUDED_)
#define AFX_CLASSFACTORY_H__3B4B8B30_5B16_4B69_ACC8_25C7259A9F74__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

extern HINSTANCE  g_hInst;
extern UINT       g_DllRefCount;

class CClassFactory : public IClassFactory  
{
protected:
	DWORD m_ObjRefCount;
public:
	CClassFactory();
	virtual ~CClassFactory();

      STDMETHODIMP QueryInterface(REFIID, LPVOID*);
   STDMETHODIMP_(DWORD) AddRef();
   STDMETHODIMP_(DWORD) Release();

      STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID*);
   STDMETHODIMP LockServer(BOOL) { return E_NOTIMPL; };
};

#endif // !defined(AFX_CLASSFACTORY_H__3B4B8B30_5B16_4B69_ACC8_25C7259A9F74__INCLUDED_) 

 
Most methods is plain and the same for all COM object classes. Method QueryInterface and  CreateInstance should be implemented accordingly for HelloExtNoATL.

In CClassFactory, this pointer is converted to IClassFactory * when the ID equals to IID_IClassFactory.

STDMETHODIMP CClassFactory::QueryInterface( REFIID riid, LPVOID *ppReturn )
{
	*ppReturn = NULL;

	if( IsEqualIID(riid, IID_IUnknown) )
	    *ppReturn = this;
	else 
	    if( IsEqualIID(riid, IID_IClassFactory) )
		*ppReturn = (IClassFactory*)this;


	if( *ppReturn )
	{
		LPUNKNOWN pUnk = (LPUNKNOWN)(*ppReturn);
		pUnk->AddRef();
		return S_OK;
	}

	return E_NOINTERFACE;
} 

In CClassFactory::CreateInstance, the COM object CShellExt is created,  then its Interface pointer is returned by its ID,.

STDMETHODIMP CClassFactory::CreateInstance( LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject )
{
	*ppObject = NULL;
	if( pUnknown != NULL )
		return CLASS_E_NOAGGREGATION;

		CShellExt *pShellExt = new CShellExt();
	if( NULL==pShellExt ) 
		return E_OUTOFMEMORY;

		HRESULT hResult = pShellExt->QueryInterface(riid, ppObject);
	pShellExt->Release();
	return hResult;
}  

Step 3: Implement the COM class

HelloExtNoAtl just extends the context menu of Windows explorer. IShellExtInit and IContextMenu should be implemented in the COM class. 
Since in pure plain C++, CShellExt inherits IShellExtInit and IContextMenu directly. Most code can be copied from the ATL sample directly.

 It also implements IUknown which is common for all COM objects.  In contract, ATL has implemented IUnknown by default. We have to code it ourself for class CShellExt. 

#if !defined(AFX_SHELLEXT_H__38EFB68B_5591_485A_9E50_409E8CDE10E2__INCLUDED_)
#define AFX_SHELLEXT_H__38EFB68B_5591_485A_9E50_409E8CDE10E2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CShellExt : public IShellExtInit, IContextMenu
{
protected:
	DWORD m_ObjRefCount;
public:
	CShellExt();
	virtual ~CShellExt();

		STDMETHOD (QueryInterface) (REFIID riid, LPVOID * ppvObj);
	STDMETHOD_ (ULONG, AddRef) (void);
	STDMETHOD_ (ULONG, Release) (void);
	

        STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);

        STDMETHODIMP GetCommandString(UINT_PTR, UINT, UINT*, LPSTR, UINT);
    STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
    STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT);
protected:
    TCHAR m_szFile [MAX_PATH];
};

#endif // !defined(AFX_SHELLEXT_H__38EFB68B_5591_485A_9E50_409E8CDE10E2__INCLUDED_)

Step 4: Registration

In ATL, a registration script is included in the project. It can be used to register and unregister a shell extension. But with plain C++, we have to implement all the registry operations manually.

Except adding registry entries for common COM objects, extra entries for shell extension also need be created. For HelloExtNoAtl, HKEY_CLASSES_ROOTFolderShellExContextMenuHandlersHelloExtNoAtl is created. Because use it will extend the context menu functions of explorer. As the entry indicates, a menu entry will be appended when the context menu of a folder is popped up. 

#include <windows.h>
#include <shlobj.h>

#include "HelloExtNoAtl.h"

#include "ClassFactory.h"
#include "Utility.h"

#include <olectl.h>

HINSTANCE   g_hInst;
UINT        g_DllRefCount;

#pragma data_seg(".text")
#define INITGUID
#include <initguid.h>
#include <shlguid.h>
#include "Guid.h"
#pragma data_seg()

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
			g_hInst = (HINSTANCE)hModule;
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
			break;
    }
    return TRUE;
}



STDAPI DllCanUnloadNow( VOID )
{
	return (g_DllRefCount ? S_FALSE : S_OK);
}




STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID *ppReturn )
{
	*ppReturn = NULL;

		if( !IsEqualCLSID(rclsid, CLSID_HelloExtNoAtl) )
	   return CLASS_E_CLASSNOTAVAILABLE;
   
		CClassFactory *pClassFactory = new CClassFactory();
	if( pClassFactory==NULL )
	   return E_OUTOFMEMORY;
   
		HRESULT hResult = pClassFactory->QueryInterface(riid, ppReturn);
	pClassFactory->Release();
	return hResult;
}





typedef struct{
   HKEY  hRootKey;
   LPTSTR lpszSubKey;
   LPTSTR lpszValueName;
   LPTSTR lpszData;
}REGSTRUCT, *LPREGSTRUCT;

STDAPI DllRegisterServer( VOID )
{
	INT i;
	HKEY hKey;
	LRESULT lResult;
	DWORD dwDisp;
	TCHAR szSubKey[MAX_PATH];
	TCHAR szCLSID[MAX_PATH];
	TCHAR szModule[MAX_PATH];
	LPWSTR pwsz;

		StringFromIID( CLSID_HelloExtNoAtl, &pwsz );

	if( pwsz )
	{
		WideCharToLocal( szCLSID, pwsz, ARRAYSIZE(szCLSID) );
        LPMALLOC pMalloc;
        CoGetMalloc(1, &pMalloc);
		if( pMalloc )
		{
	      pMalloc->Free(pwsz);
		  pMalloc->Release();
		}
    }

		GetModuleFileName( g_hInst, szModule, ARRAYSIZE(szModule) );

		REGSTRUCT ClsidEntries[] = {  
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s"),                  NULL,                   TEXT("HelloExtNoAtl"),
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s"),                  TEXT("InfoTip"),        TEXT("HelloExtNoAtl."),
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s\InprocServer32"),  NULL,                   TEXT("%s"),
        HKEY_CLASSES_ROOT, TEXT("CLSID\%s\InprocServer32"),  TEXT("ThreadingModel"), TEXT("Apartment"),
        HKEY_CLASSES_ROOT, TEXT("CLSID\%s\DefaultIcon"),     NULL,                   TEXT("%s,0"),
        NULL,              NULL,                               NULL,                   NULL};

	for( i=0; ClsidEntries[i].hRootKey; i++ )
    {
				wsprintf( szSubKey, ClsidEntries[i].lpszSubKey, szCLSID );
        lResult = RegCreateKeyEx(  ClsidEntries[i].hRootKey,
                              szSubKey,
                              0,
                              NULL,
                              REG_OPTION_NON_VOLATILE,
                              KEY_WRITE,
                              NULL,
                              &hKey,
                              &dwDisp );
   
		if( lResult==NOERROR )
		{
			 TCHAR szData[MAX_PATH];
			 wsprintf(szData, ClsidEntries[i].lpszData, szModule);
			 lResult = RegSetValueEx( hKey,
                            ClsidEntries[i].lpszValueName,
                            0,
                            REG_SZ,
                            (LPBYTE)szData,
                            lstrlen(szData) + 1);
      
			 RegCloseKey(hKey);
		}
		else
			return SELFREG_E_CLASS;
    }

		lstrcpy( szSubKey, TEXT("Folder\ShellEx\ContextMenuHandlers\HelloExtNoAtl"));
	lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT,
		szSubKey,
		0,
		NULL,
		REG_OPTION_NON_VOLATILE,
		KEY_WRITE,
		NULL,
		&hKey,
		&dwDisp);

	if( lResult==NOERROR )
	{
		TCHAR szData[MAX_PATH];
		lstrcpy(szData, szCLSID);
		lResult = RegSetValueEx( hKey,
			NULL,
			0,
			REG_SZ,
			(LPBYTE)szData,
			lstrlen(szData) + 1);

		RegCloseKey(hKey);
	}
	else
		return SELFREG_E_CLASS;

      OSVERSIONINFO  osvi;
   osvi.dwOSVersionInfoSize = sizeof(osvi);
   GetVersionEx( &osvi );

   if( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId )
   {
	   lstrcpy( szSubKey, TEXT("Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved"));
	   lResult = RegCreateKeyEx(  HKEY_LOCAL_MACHINE,
                              szSubKey,
                              0,
                              NULL,
                              REG_OPTION_NON_VOLATILE,
                              KEY_WRITE,
                              NULL,
                              &hKey,
                              &dwDisp);

       if( lResult==NOERROR )
       {
		   TCHAR szData[MAX_PATH];
	       lstrcpy(szData, TEXT("HelloExtNoAtl"));
           lResult = RegSetValueEx( hKey,
                                 szCLSID,
                                 0,
                                 REG_SZ,
                                 (LPBYTE)szData,
                                 lstrlen(szData) + 1);
      
	      RegCloseKey(hKey);
      }
	  else
		  return SELFREG_E_CLASS;
   }

   return S_OK;
}



STDAPI DllUnregisterServer( VOID )
{
	INT i;
		LRESULT lResult;
		TCHAR szSubKey[MAX_PATH];
	TCHAR szCLSID[MAX_PATH];
	TCHAR szModule[MAX_PATH];
	LPWSTR pwsz;

		StringFromIID( CLSID_HelloExtNoAtl, &pwsz );

	if( pwsz )
	{
		WideCharToLocal( szCLSID, pwsz, ARRAYSIZE(szCLSID) );
        LPMALLOC pMalloc;
        CoGetMalloc(1, &pMalloc);
		if( pMalloc )
		{
	      pMalloc->Free(pwsz);
		  pMalloc->Release();
		}
    }

		GetModuleFileName( g_hInst, szModule, ARRAYSIZE(szModule) );

		REGSTRUCT ClsidEntries[] = {  
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s"),                  NULL,                   TEXT("HelloExtNoAtl"),
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s"),                  TEXT("InfoTip"),        TEXT("HelloExtNoAtl."),
		HKEY_CLASSES_ROOT, TEXT("CLSID\%s\InprocServer32"),  NULL,                   TEXT("%s"),
        HKEY_CLASSES_ROOT, TEXT("CLSID\%s\InprocServer32"),  TEXT("ThreadingModel"), TEXT("Apartment"),
        HKEY_CLASSES_ROOT, TEXT("CLSID\%s\DefaultIcon"),     NULL,                   TEXT("%s,0"),
        NULL,              NULL,                               NULL,                   NULL};

	for( i=0; ClsidEntries[i].hRootKey; i++ )
        {
				wsprintf( szSubKey, ClsidEntries[i].lpszSubKey, szCLSID );
		lResult = RegDeleteKey(ClsidEntries[i].hRootKey, szSubKey);
        }


		lstrcpy( szSubKey, TEXT("Folder\ShellEx\ContextMenuHandlers\HelloExtNoAtl"));
	lResult = RegDeleteKey(HKEY_CLASSES_ROOT, szSubKey);


      OSVERSIONINFO  osvi;
   osvi.dwOSVersionInfoSize = sizeof(osvi);
   GetVersionEx( &osvi );

   if( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId )
   {
	   lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szSubKey);
   }

	return S_OK;
}   

Installation

The installation step is the same for all COM objects whose standard register/unregister methods are implemented. Just use regsvr32.exe to install or uninstall it.  

What Does It All Look Like?  

 Image 1

Image 2

Conclusion

After reading this article and trying the code, we can find the major difference of building a Shell Extension between ATL and plain C++. You can also read articles about creating COM objects in plain C or C++ on CodeProject.

References

COM-in-plain-C 

The Complete Idiot’s Guide to Writing Shell Extensions — Part I

History

 
October 28, 2013: Article first published.

This member has not yet provided a Biography. Assume it’s interesting and varied, and probably something to do with programming.

Лекция 7Процедура физического
проектирования – порядок, инструменты,
ресурсы, документы

Фаза разработки текста программного
продукта – фаза физического проектирования.

Выбор инструмента разработки. Определение
возможностей инструмента и сравнение
с потребностями разработки. Поиск
готовых компонент для использования в
проекте. Парадигма повторного
использования. Работа препроцессора,
трансляция, связывание, загрузка,
исполнение программ. Фазы преобразования
программ. Файлы проекта визуального
построителя и их получение в процессе
разработки. Автоматическое и ручное
создание файла ресурсов. Редактор
ресурсов. Макросы и их использование в
проекте.

«(C++Builder
Глава 4.) Препроцессор и особенности
компилятора

..о
некоторых ключевых словах C++Builder, которые
не укладываются в стандарт ANSI. Кроме
того, мы расскажем о диалоге Project |
Options, в котором задаются различные
параметры, управляющие компиляцией
программы.

Директивы
препроцессора

Препроцессорная
обработка представляет собой первую
фазу того процесса, что именуется
компиляцией программы на C/C++. Компилятор
C++Builder не генерирует промежуточного
файла после препроцессорной обработки.
Однако, если хотите, можно посмотреть
на результат работы препроцессора,
запустив отдельную программу срр32.ехе
из командной строки: срр32 myfile.c

Макроопределения

Макроопределения,
называемые в просторечии макросами,
определяются директивой препроцессора
#define. Можно выделить три формы макросов
#define: простое определение символа,
определение символической константы
и определение макроса с параметрами.
Простое определение выглядит так:
#define NDEBUG

После
такой директивы символ NDEBUG считается
определенным. Не предполагается, что
он что-то означает; он просто — определен
(как пустой). Можно было бы написать:
#define NDEBUG 1

Тогда
NDEBUG можно было бы использовать и в
качестве символической константы, о
которых говорилось в предыдущей главе.
Всякое вхождение в текст лексемы NDEBUG
препроцессор заменил бы на “I”. Зачем
нужны макроопределения, которые ничего
не определяют, выяснится при обсуждении
условных конструкций препроцессора.

Как
вы могли бы догадаться, #define может
определять не только константы. Поскольку
препроцессор выполняет просто текстовую
подстановку, можно сопоставить символу
и любую последовательность операторов,
как показано ниже:

#define
SHUTDOWN printf(«Error!»); return -1

if
(ErrorCondition()) SHUTDOWN; // «Вызов»
макроса.

Обратная
дробная черта () означает, что макрос
продолжается на следующей

строчке.
В отличие от операторов С директивы
препроцессора должны располагаться в
одной строке, и поскольку это технически
не всегда возможно, приходится явно
вводить некоторый признак продолжения.

Определенный
ранее макрос можно аннулировать
директивой #undef:

#undef
NDEBUG

После
этого макрос становится неопределенным,
и последующие ссылки на него будут
приводить к ошибке при компиляции.

Предопределенные
макросы

Компилятор
C++Builder автоматически определяет некоторые
макросы. Их можно разбить на две категории:
макросы ANSI и макросы, специфические для
C++Builder. Сводки предопределенных макросов
даны соответственно в таблицах 4.1 и 4.2.

Таблица
4.1. Предопределенные макросы ANSI

Макрос
Описание

DATE
Литеральная строка в формате “mmm dd
yyyy”, представляющая дату

обработки
данного файла препроцессором.

FILE
Строка имени текущего файла (в
кавычках).

LIME
Целое, представляющее номер строки
текущего файла.

STDC
Равно 1, если установлена совместимость
компилятора со стандартом

ANSI
(ключ -А командной строки). В противном
случае макрос не определен.

TIME
Строка в формате “hh:mm:ss”, представляющее
время препроцессорной

обработки
файла.

Значения
макросов _file_ и _line_ могут быть изменены
директивой #line (см. далее).

Таблица
4.2. Предопределенные макросы C++Builder

Макрос
Значение Описание

ВСОРТ
1 Определен в любом оптимизирующем
компиляторе.

BCPLUSPLUS
0х0540 Определен, если компиляция
производится в режиме C++. В

последующих
версиях будет увеличиваться.

BORLANDC
0х0540 Номер версии.

CDECL
1 Определен, если установлено соглашение
о вызове cdecl; в противном случае не
определен.

CHARUNSIGNED
1 Определен по умолчанию (показывает,
что char по умолчанию есть unsigned char). Можно
аннулировать ключом -К.

CONSOLE
Определен при компиляции консольных
приложений.

CPPUNWIND
1 Разрешение разматывания стека; определен
по умолчанию. Для аннулирования можно
применить ключ -xd-.

cplusplus
1 Определен при компиляции в режиме C++.

DLL
1 Определен, если компилируется
динамическая библиотека.

FLAT
1 Определен при компиляции в 32-битной
модели памяти.

MIХ86
Определен всегда. Значение по умолчанию
— 300. (Можно изменить значение на 400 или
500, применив соответственно ключи /4 или
/5 в командной строке.)

MSDOS
1 Целая константа.

MT
1 Определен, если установлена опция -WM.
Она означает, что будет

присоединяться
мультили-нейная (multithread) библиотека.

PASCAL
1 Определен, если установлено соглашение
о вызове Pascal.

TCPLUSPLUS
0х0540 Определен, если компиляция
производится в режиме C++ (аналогично
bcplusplus ).

TEMPLATES
1 Определен для файлов C++ (показывает,
что поддерживаются шаблоны).

TLS
1 Thread Local Storage. В
C++Builder определен
всегда.

TURBOC
0х0540 Номер версии (аналогичен BORLANDC ).

WCHAR
T 1 Определен только в программах C++
(показывает, что wear t — внутренне
определенный тип.

WCAR
T DEFINED 1 То же, что и WCHAR Т.

Windows
Определен для кода, используемого
только в Windows.

WIN32
1 Определен для консольных и GUI-приложений.

Как
видите, многие предопределенные макросы
C++Builder отражают те или иные установки
параметров компиляции, задаваемые в
командной строке (при ручном запуске
компилятора Ьсс32.ехе). Те же самые
установки могут быть выполнены и в
интегрированной среде через диалог
Project Options, который мы еще будем рассматривать
в этой главе.

Макросы
с параметрами

Макросы
могут выполнять не только простую
текстовую подстановку. Возможно
определение макросов с параметрами,
напоминающих функции языка С, например:

#define
PI 3.14159265

#define
SQR(x) ( (x) * (x) )

#define
AREA(x) (PI * SQR(x))

#define
MAX(a, b) (<a)>(b) ? (a): (b))

circleArea
= AREAfrl + r2);

cMax
= MAX(i++, j++);

Третье
макроопределение показывает, что макросы
могут быть вложенными. После каждого
расширения макроса препроцессор снова
сканирует полученный текст на предмет
того, не содержит ли он идентификаторов,
в свою очередь являющихся макросами.
Исключением являются случаи, когда
расширение содержит собственное имя
макроса или является препроцессорной
директивой.

Обратите
внимание на скобки в показанных ‘выше
определениях. Можно сформулировать
такое правило: каждый параметр и все
определение в целом должны заключаться
в скобки. Иначе при вхождении макроса
в выражение могут появляться ошибки,
связанные с различным приоритетом
операций. Рассмотрите такой случай:

#define
SQR(x) х*х binom = -SQR(a + b) ;

При
расширении макроса получится: binom = -a +
b*a + b;

Порядок
оценки выражения окажется совсем не
тем, что подразумевался.»

Управление генерацией текста исходного
модуля — макрогенерация. Построение
макрорасширения и средства управления
макрогенерацией. Параметры генерации
и их определение и использование.
Проверка результатов работы препроцессора
(визуальный контроль).

Фазы трансляции. Сканирование исходника.
Лексическая фаза работы транслятора.
Синтаксическая фаза. Генерация кода.
Входная и выходная информация на каждой
фазе – таблицы транслятора. Оптимизация
кода. Формат исполняемых (загрузочных)
файлов. Задачи загрузчика и представление
информации в загрузочном файле. Размещение
информации в файле и движение загрузчика
по информации.

Опции транслятора (компилятора) и
компоновщика (линкера). Управление
трансляцией и компоновкой через опции
в тексте программы. Список опций и его
применение. Настройка компилятора и
компоновщика – вкладки Compiler,Linkerдиалогового окнаProjectOptions.

Создание файлов управления работой
инструментов – командных файлов.
Компоновка разно языковых программ.

Промежуточные формы представления
программ. Таблицы транслятора, редактора
связей, загрузчика, исполнителя
(диспетчер задач). Структура объектных
модулей. Распараллеливание исполняемых
модулей на этапах компоновки, загрузки
и реализации. Настройка инструментов
преобразования программ на гиперконвейерные
возможности микропроцессора. Turbo-оболочки
— текстовой редактор, отладчик, компилятор,
построитель заданий — maker,
редактор связей. Покомандное построение
текста. Организация работы текстовых
редакторов. Стандартный набор функций
редактора. Ускорение работ по написанию
программ. Дополнительные инструменты
турбо оболочек.

Visioпостроители ,
дизайнеры. Состав инструментария
визуального проектирования. Настройка
свойств визуальных компонент. Понятие
«фокус» и принцип его использования в
визуальном проектировании. Программная
замена свойств объектов. Многообразие
визуальных построителей, их классификация
и сравнимые характеристики.

Библиотеки объектов. Инструменты
работы с библиотеками и объектами.
Набор стандартных и системных
компонент. Пакетирование компонент.
Дополнительные наборы компонент.
Создание библиотек динамической
загрузки. Пакетирование и встраивание
компонент. Пакеты времени проектирования
и времени исполнения. Использование
пакетов. Методика встраивания пакета
или отдельных компонент в библиотеку
визуального построителя и используемый
инструмент.

Основная
литература:
4 осн.[135-144,194-215,240-250]

Контрольные
вопросы:

  1. Этапы преобразования программы после
    создания исходного модуля?

  2. Что делает препроцессор?

  3. Что делает компилятор?

  4. Какие шаги составляют процесс компиляции,
    что является результатом компиляции
    и какие

таблицы строит компилятор?

  1. Что делает компоновщик и с какими
    объектами он работает?

  2. Когда необходим
    maker, что и как он
    экономит?

  3. Чем и в чем отличаются текстуальное и
    визуальное программирование?

  4. Зачем нужны пакеты и в чем их преимущества?

  5. Зачем нужны командные файлы и какова
    их роль в применении программного

инструментария?

Лекция 8. Средства визуального
программирования –MSVisualStudio,BorlandDelphiи
др.

Визуальное проектирование
программ. Визуальные
среды (Delphi,C++Builder,
Power Builder(SY
Base), Designer,
Developer(Oracle),
Visual Basic,
Visual C++
и.др).
Организация визуальной среды
проектирования.RAD-
редактор, отладчик, конструктор форм.
Оценка продуктивностиRADчерез возможности: визуальной среды
разработки, языка программирования,
библиотеки шаблонов проектирования,
компилятора, объектов хранения данных
и инструментов работы с ними, объектов
и инструментов сетевого программирования.
10 важнейших функций графической средыBorlandDelphi.
Состав меню. Назначение и глубина
построения отдельных пунктов меню.
Дерево разделов меню.Coздание,
открытие, сохранение проекта или группы
проектов и их элементов. Функции,
исполняемые разделами и пунктами меню.
Раздел инструментов – дерево инструментов
разработки. Внутренние и
внешние инструменты.
Image Editor, Win Sight, BDE, BDE Administrator, BD SQL Links, SQL
Builder, SQL Monitor, Data Pump, Team Source, Code Insight,
Repository и др.
Панель горячих клавиш и ее
использование. Панель объектов для
использования в проекте — состав, группы
компонент и набора групп, настройка
панели на индивидуального проектировщика,
пакетирование компонент. Панель
визуального редактора – инспектора
объектов. Организация доступа к свойствам
компонент. Страница событий и ее
использование для построения событийной
картины взаимодействия компонент.
Понятие фокуса. Активизация (фокусирование)
объекта при проектировании и при
исполнении программ обработки данных.
Панель формы – контейнер проекта. Одно
и многостраничные проекты. Переключение
форм и панелей при проектировании и при
исполнении. Модальность.

Типы файлов Delphi. Файлы
форм (*.dfm), ресурсов (*.res),
пакетов(*.bpl), проектов(*.dpr),
приложений – модулей (unit’s)
кадров, компонентов, общего доступа
(*.pas), опций проекта и
установок рабочего стола (*.dof,
*.dsk), резервных копий –
структура, назначение, инструменты
создания и редактирования. Менеджер
проектов и библиотека разработки. Список
расширений имен файлов, связанных с
пакетированием вDelphi:

bpl-пакетruntime, .dllфайл ОС адаптированный
кlDelphi.
Основное имя берется из .dpkили .dpkwsourceфайла.

Dcpбинарный
образ, который содержит заголовок пакета
и конкатенацию всех .dcuфайлов пакета, включая символы потребные
компилятору.Простойdcpfileсоздается для каждого
пакета. Основное имя из .dpkисточника. При использовании пакетов
.dcpфайлы обязательно
существуют.

dcu and
pas— бинарные образы
файлов модулей, входящих в пакет.
Необходимы для каждогоunit.

dpk and
dpkw– файлы источники,
созданные программистом .dpkи .dpkwпакеты идентичны,
ноdpkwрасширение используется
для кросс-платформенных приложений,
которые включают компоненты только изCLXбиблиотеки. Обычно
используют компоненты иVCLиCLXбиблиотек.

Исходный модуль программы включает:
заголовочную часть, где перечисляются
подключаемые пакеты (uses);
интерфейсную часть, где описаны
используемые типы данных, в том числе
и классы: исполнительную часть –
имплементацию, — где описаны действия
над информацией. При программировании
в С++ заголовочные (.h-header)файлы описывают
классы, а .с++ файлы -действия над
экземплярами класса. Связывание модулей
осуществляется командой #include.

Компиляция
и связывание программ. Директивы
компилятора.

«Процесс
построения программы ( С++
Builder/
Гл1)

В
этом разделе мы опишем “классический”
процесс подготовки и трансляции программы
на языке высокого уровня (в нашем случае
это C++’) в исполняемый файл, содержащий
машинные инструкции и все остальное,
что необходимо для работающей программы
системы Windows. В C++Builder, как мы увидим в
дальнейшем, детали этого процесса в
основном скрыты от программиста и, кроме
того, имеются дополнительные моменты,
обусловленные спецификой визуального
подхода к программированию. Создание
программы на языке C++ выглядит примерно
так. Прежде всего, программист с помощью
того или иного текстового редактора
готовит файлы исходного
кода

на C/C++. После этого происходит построение
программы, в котором можно выделить
такие этапы:

  • Компиляциюисходных файлов в файлыобъектного
    кода
    (с расширением .obj).

  • Компоновкуобъектных файлов с присоединением
    необходимыхбиблиотек(в том числе,
    возможно, динамических), в результате
    чего получается ужемашинный код.

  • Компоновку
    ресурсов
    (ресурсы включают в себя
    битовые матрицы, курсоры, строковые
    таблицы, пиктограммы и т.п.). Это
    завершающий этап, на котором формируется
    конечный ехе-файл, запускаемый на
    выполнение. Этот процесс иллюстрируется
    рис. 1.1.

 

Рис.
1.1
Упрощенная
схема построения программы

1.
Source1.cpp
2. Source2.cpp
3. Source3.cpp 4. Компилятор

5.
Source1.obj 6. Source2.obj 7. Source3.obj 8. Addon.lib

9.
Код запуска 10. Исполнительная библиотека
11. Ресурсы App.res 12. Компоновщик

13.
Компоновщик ресурсов

14.
Приложение
App.exe

Некоторые
системы (и в том числе C++Builder) сразу
выполняют компоновку объектных файлов
с ресурсами, совмещая два последних
этапа. Что касается первого шага —
компиляции — то здесь возникает одна
проблема, которую стоит обсудить.

Проблема
раздельной компиляции

Когда-то
давно программа для машины вроде БЭСМ-4,
написанная на языке Алгол-60 или FORTRAN,
состояла из одного-единственного файла,
а точнее, являлась просто одной “колодой”
перфокарт. Также и первые версии языка
Pascal для PC (например, Turbo Pascal 2) допускали,
по существу, компиляцию только программ,
состоящих из единственного исходного
файла. Компилятор “видел” сразу весь
текст программы и мог непосредственно
проконтролировать, например, количество
и тип фактических
параметров в вызове процедуры, —
соответствуют ли они тем, что указаны
в заголовке ее определения (формальным
параметрам). Компилятор транслировал
программу сразу в машинный код (исполняемый
файл). С ростом сложности и объема
программ пришлось разбивать их на
несколько файлов исходного кода.
Соответственно трансляция программы
распалась на два этапа — компиляции,
на котором каждый из исходных файлов
транслируется в файл объектного кода,
и компоновки, в результате которой из
нескольких объектных файлов получается
конечный исполняемый файл. При этом
необходимо произвести, как говорят,
разрешение
адресных ссылок,

когда, например, основной файл программы
обращается к вспомогательной процедуре,
находящейся в другом файле.

Компилятор
C/C++ генерирует стандартные объектные
файлы с расширением .obj. (Их формат
определен фирмой Intel и не зависит от
конкретной операционной системы.) Файлы
эти содержат машинный код, который
снабжен дополнительной информацией,
позволяющий компоновщику разрешать
ссылки между объектными модулями. Так,
в начале файла формируются две таблицы:
таблица глобальных символов (это имена
объектов, определяемых в данном файле,
на которые могут ссылаться другие модули
программы) и таблица внешних ссылок
(имена объектов в других файлах, к которым
обращается данный модуль). Пользуясь
информацией этих таблиц, компоновщик
модифицирует код, подставляя в него
соответствующие адреса.

Проблема
состоит в том, что в объектном файле
отсутствует информация, которая позволяла
бы проверить корректность вызова
процедуры (т.е. количество и тип ее
параметров), находящейся в другом файле.
Ведь компилятор обрабатывает файлы
исходного кода по отдельности.

Вязыке Turbo Pascal (и позднее — в Delphi) эта
проблема была решена благодаря определению
специального формата промежуточных
файлов. Эти “объектные” файлы (в Delphi
они имеют расширение ,dcu) содержат, помимо
всего прочего, информацию о параметрах
процедур и функций, об определяемых в
модуле типах данных (классах) и т.д.

C/C++
был задуман как максимально универсальный
язык, и потому он не может использовать
нестандартный формат объектных файлов.
Это сделало бы невозможным, например,
создание файлов подпрограмм, которые
могли бы включаться в программы,
написанные на других языках. Возможность
раздельной компиляции обеспечивается
в C/C++ применением заголовочных
файлов,

присоединяемых к компилируемым исходным
файлам на этапе препроцессорной
обработки.

Заголовки содержат прототипы
функций,

объявления типов и другую информацию,
необходимую для раздельной компиляции
исходных модулей программы. Заголовочные
файлы (они имеют расширение .h или .hpp)
подключаются к компилируемому файлу
исходного кода (.с или .срр) с помощью
директивы
препроцессора

#include, за которой следует имя заголовочного
файла в кавычках или угловых скобках,
например:

#include
<stdlib.h> или
#include «myfile.h»

Препроцессор
заменяет директиву #include содержимым
указанного файла; после завершения
препроцессорной обработки полученный
текст передается компилятору, который
транслирует его в объектный код.

Во
многих системах программирования на
C/C++ препроцессор составляет единое
целое с компилятором (это верно и для
C++Builder). Тем самым ускоряется компиляция
исходных файлов, и нет необходимости
создавать промежуточный файл, содержащий
обработанный препроцессором код. Однако
в C++Builder имеется отдельный препроцессор
срр32.ехе, запускаемый из командной
строки. Вы можете им воспользоваться,
если нужно просмотреть текст, получаемый
в результате препроцессорной обработки;
это может быть полезно, например, при
отладке макросов препроцессора. Директивы
препроцессора будут подробно
рассматриваться в 4-й главе.

Один
и тот же заголовок можно подключать ко
многим исходным файлам. Таким образом,
отдельно компилируемые модули получают
доступ к необходимой информации о
процедурах и прочих элементах программы,
определяемых в других модулях. Кроме
того, это гарантирует, что размещенное
в заголовочном файле объявление типа
или функции будет одним и тем же во всех
компилируемых файлах, и любые внесенные
в него изменения будут автоматически
воздействовать на все модули программы.

О
библиотеках

Выше
мы уже упоминали о библиотеках, не
объясняя, впрочем, что они собой
представляют. Конкретнее, мы имели в
виду библиотеки
объектных модулей;

такая библиотека является просто
собранием модулей объектного кода,
скомпонованных в одном файле с расширением
lib, своего рода архивом. На рис. 1.1 показана
гипотетическая библиотека пользователя
Addon.lib. Она могла бы быть создана из
нескольких объектных модулей путем
обработки их библиотекарем
tlib32.exe.

На
рисунке показаны также код запуска и
исполнительная библиотека языка C/C++.
Это необходимые элементы компоновки
любой программы на С. Код запуска
исполняется перед тем, как управление
будет передано на входную точку вашей
программы (функцию main, WinMain и т. п.). Среди
задач, им выполняемых, можно указать
следующие:

  • инициализация
    исполнительной библиотеки

  • конструирование
    глобальных объектов C++

  • завершение
    программы при отсутствии необходимых
    ресурсов.

Исполнительная
библиотека содержит разнообразные
процедуры общего назначения, которые
вы можете вызывать в своей программе.
В частности, библиотека обеспечивает:

  • управление
    файлами

  • управление
    памятью

  • преобразование
    данных и многое другое.

Что
касается динамически
присоединяемых библиотек —

DLL, — то во многих случаях они, с точки
зрения программиста, мало чем отличаются
от обычных, статически
компонуемых

библиотек объектных модулей. Функция,
которая находится в DLL, вызывается так
же, как и всякая другая функция. Правда,
“снаружи” динамическая библиотека
выглядит скорее как исполняемый файл;
эти библиотеки создаются не библиотекарем,
а компоновщиком. Вообще-то вопросы
разработки и использования DLL выходят
за рамки этой книги, но в следующей главе
мы приведем пример простейшей DLL, чтобы
читатель получил представление о том,
как это делается в C++Builder. Каждая
библиотека, как правило, сопровождается
своим заголовочным файлом (их может
быть и несколько), который определяет
интерфейс ее функций и других элементов.
Исходный код библиотеки может быть и
недоступен для программиста. Но в ее
заголовочном файле (или файлах) имеется
все необходимое для использования
библиотеки в прикладной программе.»

Результаты
компиляции Список опций компилятора и
компоновщика. «Управление
компилятором (С++
Builder)В
этом разделе мы рассмотрим установки
диалога Project Options, имеющие отношение к
программам на С. В основном это будет
касаться страниц Compiler и Advanced Compiler этого
диалога. Он открывается выбором Project |
Options в главном меню.

Страница Compiler показана на рис. 4.1. В
нижней части страницы вы видите две
кнопки: Full debug и Release. Первая из них
выполняет все установки параметров,
позволяющие в полной мере использовать
возможности отладчика C++Builder; вторая
запрещает генерацию какой-либо отладочной
информации и оптимизирует код для
получения максимальной скорости
выполнения. При изучении языка вам лучше
всего воспользоваться кнопкой Full debug и
не задумываться больше об установках,
влияющих на отладку и эффективность
кода.

  • Группа
    радиокнопок Code optimizationпозволяет
    полностью отключить оптимизацию, задать
    оптимизацию по скорости или выбрать
    отдельные опции оптимизации, включив
    радиокнопку Selected и нажав Optimizations. При
    этом откроется окно диалога со списком
    опций, в котором, кстати, показаны
    эквивалентные ключи командной строки,
    управляющие оптимизацией.

  • Группа
    Warnings
    управляет выдачей предупреждений.
    Включив соответствующую радиокнопку,
    можно запретить все, разрешить все
    предупреждения или управлять выдачей
    отдельных предупреждений. Диалог
    Compiler Warnings также показывает ключи
    командной строки. Я бы советовал вам
    разрешить выдачу всех предупреждений.
    Грамотно написанный код должен
    транслироваться не только без ошибок,
    но и без всяких замечаний со стороны
    компилятора.

  • Раздел
    Pre-compiled headers
    управляетпрекомпиляцией
    заголовочных файлов.

Объем
кода заголовочных файлов, включаемых
в модуль исходный модуль, может достигать
тысяч, если не десятков и сотен тысяч
строк. К тому же часто эти заголовочные
файлы включаются в каждый модуль проекта.
Поскольку при разработке программы
заголовочные файлы приходится изменять
сравнительно редко (а стандартные
заголовки вообще не меняются), имеет
смысл компилировать все необходимые
заголовки один раз и создать файл
специального вида, который будет
содержать всю необходимую “заголовочную”
информацию в форме, обеспечивающей
максимально быстрый доступ к ней.
Компилятор C++Builder может генерировать
такие файлы (с расширением .csm), •во много
раз ускоряющие повторное построение
проектов. Недостатком их можно считать
разве что весьма большой размер —
типичный файл прекомпилируемых заголовков
может занимать от пяти до десяти мегабайт.

Кнопка None запрещает использование
прекомпилируемых заголовков. Кнопка
Use pre-compiled headers разрешает генерацию и
использование файла компилированных
символов (это другое название файлов
.csm). Кнопка Cache pre-compiled headers заставляет
компилятор кэшировать прекомпилируемые
заголовки, т. е. хранить их информацию
в памяти, а не загружать csm-файл заново,
когда в этом возникает необходимость.
Это полезно, когда вы транслируете сразу
несколько файлов, но может и замедлять
компиляцию, если память

Рис.
4.1
Страница
Compiler
диалога
Project Options

  • В поле
    редактирования File name задается имя файла
    компилированных символов.

  • В поле
    Stop after можно ввести имя файла, после
    компиляции которого генерация
    прекомпилируемых заголовков прекращается.
    Это должен быть файл, включаемый в
    исходный модуль непосредственно, а не
    в другом заголовке (как, например,
    windows.h включает массу других заголовочных
    файлов)

  • Раздел
    Debugging
    управляет включением отладочной
    информации в объектные файлы, создаваемые
    компилятором (флажки Debug information и Line
    numbers). Кроме того, флажок Disable inline
    expansions позволяет запретить расширения
    inline-функций, т. е. непосредственную
    вставку кода функции на месте ее вызова.
    Это упрощает отладку.

Если
вы хотите отлаживать программу, то
должны убедиться, что флажок Create debug
information на странице Linker также установлен
.

  • Раздел
    Compiling
    управляет общими аспектами
    компиляции. При помеченном флажке Merge
    duplicate strings компилятор сопоставляет
    встречающиеся литеральные строки и,
    если две или более строк совпадают,
    генерирует только одну строку. Это
    делает программу несколько более
    компактной, но может приводить к ошибкам,
    если вы модифицируете одну из строк.
    При установке флажка Stack frames компилятор
    генерирует стандартныекадры стекафункций, т. е. стандартный код входа и
    возврата. Этот флажок должен быть
    установлен, если вы хотите отлаживать
    ‘функции модуля. Если флажок сброшен,
    то для функций, не имеющих параметров
    и локальных переменных, будет
    генерироваться нестандартный, сокращенный
    код. При установке Treat enum types as ints
    компилятор отводит под перечисления
    4-байтовое слово. Если флажок сброшен,
    отводится минимальное целое (1 байт,
    если значения перечислимого типа лежат
    в диапазоне 0-255 или -128-127). Show general messages
    разрешает выдачу общих сообщений
    компилятора (не являющихся предупреждениями
    или сообщениями об ошибках). Флажок
    Extended error information разрешает выдачу
    расширенных сообщений об ошибках
    компилятора (вплоть до контекста
    синтаксического анализатора и т. п. —
    простому человеку ни к чему).

Страница
Advanced Compiler Эта страница (рис. 4.2) позволяет
управлять деталями генерации объектного
кода.

Рис.
4.2
Страница
Advanced Compiler
диалога
Project Options

  • Группа
    радиокнопок Instructionset задает тип
    процессора целевой системы. Установки
    этой группы эквивалентны ключам
    командной строки -3, -4, -5 и -6.

  • Группа
    Data alignment
    управляет выравниванием
    данных в памяти. Выравнивание может
    отсутствовать (Byte), либо данные могут
    располагаться по адресам, кратным 2, 4
    или 8 байтам. В структурах, если необходимо,
    вводятся байты заполнения. Установки
    группы эквивалентны ключам командной
    строки-an,гдеп —1, 2, 4 или 8.

  • Группа
    Calling convention
    задает соглашение о вызове,
    применяемое по умолчанию. (Register обозначает
    соглашение _fastcall.) Эквивалентные ключи
    командной строки — -рс (или -р-), -р, -рг
    и -ps.

  • Группа
    Register variables
    управляет созданием
    регистровых переменных. None запрещает
    их использование. Automatic разрешает
    компилятору размещать переменные в
    регистрах там, где это целесообразно,
    и Register keyword разрешает размещать в
    регистрах только переменные, объявленные
    как register. Радиокнопки соответствуют
    ключам -г-, -г и -rd.

  • Раздел
    Output
    имеет
    два флажка:
    Autodepedency information и Generate

  • underscores.
    Первый из них определяет, будет ли
    включаться в объектный файл информация
    о зависимостях между исходными файлами
    (необходимо для работы команды Make).
    Второй флажок указывает, что имена
    функций _cdecl должны снабжаться начальным
    символом подчеркивания. Установленные
    флажки соответствуют ключам -Х- и -и.

  • Раздел
    Floating point
    управляет генерацией кода
    арифметики с плавающей точкой. None
    показывает, что ваш код не использует
    чисел с плавающей точкой. Fast исключает
    промежуточные преобразования типов
    при арифметических вычислениях, как
    явные, так и неявные;

при
сброшенном флажке все преобразования
выполняются в строгом соответствии с
правилами ANSI С. Correct Pentium FDIV генерирует
код, исключающий возможность ошибки
из-за дефекта в ранних версиях процессора
Pentium. Соответствующие ключи командной
строки — -f-, -ff и -fp.

  • Группа
    радиокнопок Language complianceзадает
    версию языка, с которой совместим
    компилируемый исходный код. Вы можете
    выбрать стандартный ANSI С, С с расширениями
    Borland, “классическую” версию Кернигана-Ричи
    и язык Unix V. При написании приложений
    Windows имеет смысл выбрать либо ANSI, либо
    Borland, если вы хотите использовать
    какие-либо ключевые слова из расширенного
    набора, описанного в этой главе. Флажкам
    соответствуют ключи -A (ANSI), -AT или -A-
    (Borland), -АК (К & R) и -AU (Unix V).

  • Раздел
    Source
    управляет некоторыми аспектами
    интерпретации исходного кода. Флажок
    Nested comments разрешает вложенные С-комментарии,
    т. е. конструкции вида /*…/*…*/…*/. MFC
    compatibility позволяет транслировать код
    библиотеки MFC, используемой компилятором
    Microsoft Visual С. Поле Identifier length задает
    максимальное число значимых символов
    в идентификаторах языка С (в C++ длина
    идентификаторов не ограничивается).

Страница
Directories/Conditionals. На этой странице диалога
Project Options (рис. 4.3) расположены несколько
полей редактирования, позволяющих
задавать стандартные каталоги по
умолчанию — библиотек, заголовочных
файлов и т. д. Нас на этой странице
интересует сейчас только раздел
Conditionals.

В
поле Conditional defines можно определять символы
C/C++, языка Object Pascal и компилятора ресурсов,
которые будут, например, управлять
директивами условной компиляции в
исходных файлах. Для присвоения символам
значений используется знак равенства.
Можно ввести в это поле сразу несколько
определений, отделяя их друг от друга
точкой с запятой, например:

NDEBUG;ххх=1;yyy-YES

Для
ввода определений можно также
воспользоваться редактором строк,
отрывающимся при нажатии кнопки с
многоточием. В командной строке символы
определяются с помощью ключа -D:bcc32
-DNDEBUG
-Dxxx=l
-Dyyy=YES

Мы
немного рассказали о ключах командной
строки компилятора не столько для того,
чтобы вы умели запускать bcc32.ехе вручную,
а чтобы дать вам некоторые
г
начальные сведения, которые помогут
вам разбираться в Ьрг-файлах проектов
C++Builder. Полное руководство по запуску
компилятора из командной строки вы
можете найти в оперативной справке в
разделах command-line compiler и command-line options.

Рис.
4.3
Страница
Directories/Conditronals

Возможности управления компиляцией и
связыванием. Защита от повторного
запуска приложений.

Инструменты VisualStudioих назначение и
использование. Дерево возможностейMSVisualStudio.MS Visual Studio(MSV) ( Source Safe, Enterprise
Tools, Tools, Language (Basic, C++,
Fox Pro, Interdev)) – назначение
каждого раздела
и его состав.
Особенности сетевого проектирования.

Основная
литература:
5осн.[
3,4]C++Buildergl1,2,14Delphi7gl1

Контрольные
вопросы:

  1. Состав
    визуального построителя программ?

  2. Какие
    визуальные среды построения ПП Вам
    известны?

  3. Чем характерны
    сетевые среды разработки и реализации
    программ?

  4. Как
    настраивать среду разработки на
    разработчика?

  5. Как
    реализуется событийная составляющая
    в программах?

  6. Как
    минимизировать повторные работы при
    отладке ПП?

  7. Чем отличается
    запись объектов в DelphiиC++?

  8. Что такое
    библиотека компонент?

  9. Как
    структурирована библиотека компонент?

  10. Какие
    технологии позволяют вести визуальное
    построение ПП?

  11. Какие файлы
    входят в состав визуально созданного
    проекта ПП?

Лекция 9Подбор и редактирование
компонент, разработка компонент.OpenТOOLsAPI.

Организация визуальной среды — инспектора
свойств, событий и их использование.
Методика доступа и изменения свойств
объектов во время проектирования и
исполнения программ. Списки значений
свойств. Свойства, отображающие поведение
и визуализацию объекта. TObject(TPersistent(TComponent(TControl(TGraphicControl,TWinControl)))) – дерево компонент.

MAKE.EXE–
утилита для управлениякомпиляцией и
линковкой в процессе отладки программы.
РаботаMAKEоснована на
временных и информационных зависимостях
между исходными и объектными файлами.
При повторной компиляции и связыванииMAKEизменяет ( компилирует,
связывает) только те файлы, которые
модифицируются при отладке, что
существенно снижает время подготовительной
работы. Необходимость перекомпиляции
файла определяется по временным меткам,
т.е. если время изменений файла и время
текущей компиляции проекта совпадают,
производится перекомпиляция В текстеMAKEпрограммы записаны
правила перестройки программ проекта
и источники для выполнения этих работ.
Синтаксис для
MAKE программ:

MAKE [options…] [target[target]]

options

are
MAKE options that control how MAKE works

target

is the
name of the target listed in the makefile that you want to build

Набор стандартных компонент разработки.
Графические компоненты. Палитра
компонент, предоставляемая разработчику
– состав, назначение страниц палитры,
визуальные и не визуальные компоненты
(свойство видимости), изменение
представления и места размещения
компоненты на форме (свойства
визуализации).При работе с графикой
используются два термина — drawingandpainting.Drawingиспользуется при
создании элементарных графических
объектов (линии, фигуры) в кодовом
представлении. Для этого используется
панель отрисовки — палитра (objectcanvas) и методы объектаcanvas.Painting– понятие, которое означает манипулирование
элементарными графическими объектами.
Следующий список действий дизайнера
позволяет упростить работу с графикой.

Refreshing the screen (Перерисовка
экрана)

Types of graphic objects (Типы
объектов)

Common properties and methods of canvases (Общие
свойства и
методы палитры)

Handling multiple drawing objects in an
application (Ручное рисование
в приложении)

Drawingonabitmap(Рисование на битовом
поле)

Loadingandsavinggraphicsfiles(Загрузка и сохранение
графических файлов)

Using the clipboard with graphics (Использование
буфера для
графики)

Rubber banding example (Пример)

Создание компонент и пакетов компонент,
их использование. Методика визуального
проектирования компонент. Подключение
и разработка собственных компонент.
Можно создать новый компонент двумя
способами – вручную или с использованием
мастера компонент (Componentwizard). Можно создать
компонент с минимальной функциональностью
и инсталлировать его на палетту компонент.
Затем протестировать его вdesigntimeandruntime.
Затем можно дополнять компонент
свойствами, событиями методами, проводя
тестирование. Основные шаги
разработки:

1 Create a unit for the new component. (Создать
модуль для нового компонента)

2 Derive your component from an existing component
type. (Определить родительский
тип)

3 Add properties, methods, and events. (Добавить
свойства, методы,
события).

4 Register your component with the IDE.
(Регистрировать компонент)

5 Create a bitmap for the component. (Создать
ярлык)

6 Create
a package (a special dynamic-link library) so that you can install
your component in the IDE.

7 Create a Help file for your component and its
properties, methods, and events. (Создать помощь).

По завершению работ вы получите следующие
файлы:

Apackage(.BPL)orpackagecollection(.DPC)file(файлы пакета или
коллекции)

A compiled package (.DCP) file (файл
компиляции)

A compiled unit (.DCU) file (объектный
файл)

A palette bitmap (.DCR) file (файл
ярлыка)

A Help (.HLP) file (файл
помощи)

Интерфейсы OpenToolsAPIПостроение мастеров.
Все функции инструментария -ToolsAPI- продекларированы в
одном модуле,ToolsAPI. Для
использования модуль вставляют в пакет
разработки, что приводит к появлению
добавляемогоdesign-timepackageили созданиюDLL,
вставляемого вruntimepackages.

Основной интерфейс для написания
инструментов — ToolsAPI– сосредоточен вIOTAWizard,
т.е. большинствоIDEadd-ins(добавок-вставок) вызываются мастерами.
МастераC++BuilderиDelphi, для большинства
инструментов интероперабельны
(переносимы, межплатформенны), т.е. можно
создатьwizardinDelphi, а затем использовать
его вC++Builder.

Для использования ToolsAPI, пишутсяwizardclasses, которые имплементируют
интерфейсы, определенные вToolsAPIunit. Мастер использует
сервисы, которые предлагаетToolsAPIКаждый сервис –
интерфейс, который представлен группой
функций. Имплементация интерфейса
скрыта вIDE.ToolsAPIделают доступным только
интерфейс но не его имплементацию.
Переменные сервисов делают доступными
редактор исходников,дизайнер форм,
отладчик и т.д.(sourceeditor,formdesigner,debugger,andsoon.See Obtaining Tools
API services for information about using the interfaces that expose
services to your wizard).

Сервисы и другие интерфейсы разделены
на две категории, что зафиксировано в
префиксах — NTAиOTA.NTA(nativetoolsAPI) обеспечит прямоц доступ
к действующимIDEобъектам,
таким, например, какTMainMenu.
Когда используется такой интерфейс, мы
привязываемся к специфической версииIDE. Результат может быть
представлен какdesign-timepackageили какDLLфайлruntimepackages.OTA(opentoolsAPI) не требует пакетирования
и доступа кIDEтолько через
интерфейс. Теоретически, можно написатьwizardна любом языке, который
поддерживаетCOMинтерфейсы.OTAинтерфейсы не гарантируют
полный доступ кIDE, но
обеспечат полноту функций доступных
черезOTAinterfaces.
Еслиwizardиспользует толькоOTAinterfaces,
возможно написатьDLLкоторые не зависят от специфических
версийIDE.

ToolsAPIпорождает два вида интерфейса, тот,
который имплементирует программист и
тот, который имплементируетIDE.
Большинство последних определяют
возможностиIDE, но скрывают
имплементацию возможностей. Наследники
интерфейсов которые имплементируете
вы делятся на три категории: мастера
(wizards), описатели (notifiers),
создатели (конструкторы,creators):

Как сказано ранее, wizard
classимплементируетIOTAWizardинтерфейс и измененные
интерфейсы. Описатели (notifier)
– другой вид интерфейсов, которыеIDEиспользует для определения обратного
вызова к скрытым объектам. Пишется
класс, который имплементируетnotifierinterface, который затем
регистрируем черезToolsAPI, и затем используется
обратный вызов для открытия файлов,
редактирования исходного кода, старта
сессии отладчика и т.п.. Описатели скрыты
в описанииIDEсобытий.

Конструктор (creator)
другой тип интерфейсов, который
необходимо имплементировать. Используется
для создания новых модулей, проектов и
других файлов, или для открытия
существующих.

Связывание объектов программ. Построение
отчетов. Менеджеры, редакторы, мастера
(wizards). Мастер построения
компонент -Componentwizard–упрощает создание нового компонента.
Для создания необходимо: 1) определить
родительский класс (Theclassfromwhichthecomponentisderived.); 2) дать имя новому
классу (Theclassnameforthenewcomponent.);
3) определить страницу палетты компонент,
на которую будет установлен новый (TheComponentpalettepagewhereyouwantittoappear.); 4) определить имя
модуля, в котором создается компонент
(Thenameoftheunitinwhichthecomponentiscreated.); 5) указать путь к
модулю – полное имя (Thesearchpathwheretheunitisfound.); 6) определить имя
пакета, где размещается новый компонент
(Thenameofthepackageinwhichyouwanttoplacethecomponent.).

Мастер компонент (Componentwizard) реализует 3 задачи,
при создании компонента вручную: создание
модуля (Creatingaunit); изменение компонента
(Derivingthecomponent): регистрация
(Registeringthecomponent). Мастер не может
добавить компонент в существующий
модуль. Необходимо вручную добавлять
компонент в существующий модуль.

Основная
литература:
5 осн. [3]C++Вuilder–gl15

Контрольные
вопросы:

  1. Как можно
    создать собственный компонент?

  2. Какие
    программные инструменты используются
    при создании компонент?

  3. Чем
    отличаются категории интерфейсов и
    сервисов с префиксами NTAиOTA?

  4. Какова
    последовательность действий разработчика
    компонент?

  5. В чем
    различается работа при создании
    исполняемых файлов компонент вида dllиexe?

Лекция 10. Построение интерфейса
программы. Принципы разработки
инструментария. Инструментальные
средства и методы построения интерфейса.

« (Delphi7,
гл.8)Компонент TActionList , это — централизованное
хранилище, где воздействия со стороны
пользователя связываются с реакциями
на них.

Действием (Action) будем именовать операцию,
которую пользователь хочет произвести,
воздействуя на элементы интерфейса.
Тот компонент, на который он хочет
воздействовать, называется целью
действия (Action target). Компонент, посредством
которого действие инициировано (кнопка,
пункт меню), — клиент действия (Action
client). Таким образом, в иерархии классов
Delphi действие TAction — это невизуальный
компонент, который играет роль «черного
ящика», получающего сигнал от одного
или нескольких клиентов, выполняющих
действия над одной (или разными) целями.

Примечание 
Действия могут работать только будучи
объединенными в список компонентов
TActionList или TActionManager. Вне этих компонентов
применение действий невозможно.

Спроектировав на бумаге
пользовательский интерфейс, начните
работу с помещения на форму компонента
TActionList. Он находится в Палитре компонентов
на первой странице Standard
(вот видите какое ему
уделяется внимание!). После этого следует
запустить редактор списка действий
двойным щелчком мышью на компоненте
или с помощью контекстного меню .

Добавление действий. Для программиста
предусмотрен набор типовых, наиболее
часто встречающихся действий, которые
описаны в следующем разделе. Помимо них
можно вставить и обычное действие,
которое получит имя Action1. Итак, что же
из себя представляет действие? ..

События, связанные с
действиями
Компонент
TAction реагирует на три события:
OnExecute, OnUpdate И OnHint.

Первое — и самое главное — должно быть
как раз реакцией на данное действие.
Это событие возникает в момент нажатия
кнопки, пункта меню — короче, при
поступлении сигнала от клиента действия.
Здесь — как правило—и пишется обработчик.
Почему «как правило»? Потому что
схема обработки сигнала 4-этапная:

1. Сначала вызывается обработчик события
OnExecute списка действий

TActionList:

property
OnExecute: TActionEvent; TActionEvent = procedure (Action:
TBasicAction; var Handled: Boolean)

of object;

Если обработчик этого события вами не
предусмотрен, или в параметре Handled он
вернул значение False, происходит генерация
следующего события — шаг 2.

2. Вызывается обработчик события
onActionExecute глобального объекта Application
(тип события тот же — TActionEvent). Если и оно
не обработало сигнал действия, переходим
к следующему шагу.

3. Вызывается обработчик события onExecute
самого действия (объекта типа TAction или
его потомка).

4. Если первые три шага не обработали
ситуацию (вернули False), то, вероятно, это
было связано с неправильной целью
(Target) действия. В качестве «последнего
шанса» приложению посылается сообщение
CM_ACTIONEXECUTE. В этом случае происходит поиск
другой цели для данного действия (об
алгоритме поиска цели см. ниже).

Первые две возможности в этом списке
используются относительно редко. Тем
не менее они полезны, если вам нужно
глобально добавлять/удалять/разрешать/запрещать
действия.

Введение события onupdate
является очень хорошей находкой, о нем
напишем подробно. И автор этих строк,
и, возможно, вы потратили немало времени,
чтобы в разрабатываемых программах
элементы управления находились в
актуальном состоянии. Если, скажем,
вашей программой открыт первый файл,
то нужно активировать ряд кнопок и
пунктов меню (Save, Save
as
, Print
и т. п.); как только
закрыт последний — отключить их. Если
в буфере обмена есть что-то подходящее,
необходимо активизировать пункт меню
и кнопку Paste, если
нет — отключить. В результате код,
отслеживающий это, у неопытных
программистов «размазывается» по
всему приложению. А ведь можно поступить
проще. Событие TAction.onUpdate возникает в
моменты простоя приложения, т. е. тогда,
когда оно не занято обработкой сообщений
(цикл содержится в методе idle объекта
Application). Это гарантирует, что оно возникнет
ДО ТОГО, как пользователь щелкнет мышью
и увидит выпадающие пункты меню; поэтому
можно успеть обновить их состояние.
Пример
использования
события
onupdate:

procedure
TForml.PasteActionUpdate(Sender: TObject); begin

TAction(Sender).Checked
:= Clipboard.HasFormat(CFJTEXT);

 end;

Примечание
Перед вызовом события onupdate также
происходит 4-этапная последовательность
действий, точно такая же, как при
OnExecute.

Третье событие имеет такой тип:

THintEvent
= procedure (var HintStr: string; var CanShow: Boolean) of object;

Оно вызывается тогда, когда от элемента
управления требуется показать подсказку,
связанную с данным действием. В обработчике
события можно указать, будет ли что-нибудь
показываться (параметр CanShow) и, если да,
то что именно (параметр Hintstr).

Это были события, относящиеся к компоненту
TAction. Сам компонент TActionList также имеет
три события: OnExecute, OnUpdate И OnChange. О первых
двух мы уже сказали; третье происходит
в момент изменения списка (добавления
или удаления действий).

Свойства, распространяемые на клиентов
действия
Если у нескольких кнопок
или пунктов меню общий обработчик,
разумно потребовать, чтобы у них были
и другие общие свойства. Так оно и
реализовано в Delphi. Действие также можно
снабдить картинкой. Компонент TActionList
связывается со спискомкартинок
TimageList, а действие TAction — с конкретной
картинкой через свойство imageindex. Таким
образом, все элементы управления,
связанные с действием, — кнопки и пункты
меню — будут иметь одну и ту же картинку.

Если вы не думаете о переносе
своего приложения в среду Linux, то имеются
все основания воспользоваться потомком
TActionList — компонентом TActionManager
(далее в тексте —
менеджер действий). Более современный
и «продвинутый» он обеспечит вас
многими дополнительными возможностями.
Будучи применен сам по себе, компонент
TActionManager ничем не отличается от
предшественника. Отличия проявляются,
если действия из этого компонента
разместить на специальных панелях —
TActionMainMenuBar (будем называть его панелью
главного меню) и TActionToolBar (далее — панель
действий).

На первой странице редактора
TActionManager (вызывается двойным щелчком
или командой Customize из
контекстного меню) как раз и содержится
список всех панелей, связанных с данным
менеджером действий. Вы можете добавить
новый или убрать компонент TActionToolBar
нажатием кнопок New
и Delete соответственно.
С компонентом TActionMainMenuBar так по понятным
причинам поступить нельзя — меню
полагается иметь одно.

Когда вы перетаскиваете действие на
панель, на нем появляется специальный
компонент, похожий на пункт меню или
кнопку. Его роль — служить клиентом
данного действия. Поэтому, естественно,
он сразу и автоматически получает нужные
Caption, imageindex, Hint и прочие общие для всех
клиентов свойства, о которых говорилось
выше. Класс этого клиента — TActionclientitem;
будем называть их псевдокнопками или
псевдоэлементами.

При перетаскивании нет особых сложностей,
но надо иметь в виду следующие аспекты:

  •  при
    перетаскивании всей категории на панель
    главного меню она появляется в виде
    пункта меню верхнего уровня и содержит
    при этом все свои дочерние действия;

  •  при
    перетаскивании всей категории на панель
    действий создаются псевдокнопки для
    всех дочерних действий в категории.
    Логично поступить по принципу «одна
    категория — одна панель действий»,
    это будет полезно для настройки
    интерфейса пользователем;

  •  если
    вы ошиблись при перетаскивании, не
    нажимайте кнопку Delete
    — при этом удалится
    не только псевдокнопка, но и само
    действие. Перетяните ненужный
    псевдоэлемент за пределы панелей
    действий, тогда он будет удален;

  •  если
    вы уже перетянули категорию на панель
    главного меню, а потом решили добавить
    к ней действия, то вам придется убрать
    соответствующий ей псевдоэлемент и
    перетянуть всю категорию заново. Либо
    воспользоваться ручным способом,
    который описывается ниже. »

Стандартный интерфейс систем. Пример
разработки интерфейса – MSVisualSystems,BorlandVisualSystems,OracleVisualSystemsи
др. Решения, достоинства, недостатки,
характеристики – мобильность, глубинность,
цвет, размерность, анимация, масштабируемость,
надежность, скорость доступа и др..
Элементы стандартных интерфейсов систем
и их компонентная реализация. .

Минимизация вмешательства. Уровень
автоматизации и защиты от некомпетентности.
Сеансы и цепочки действий. Использование
шаблонов и предистории. Многообразие
и мобильность представления. Использование
систем, – инструментов, деловой графики.

«
Как избежать одновременного запуска
двух копий одного приложения.

Такая
задача возникает очень часто. Многие,
особенно начинающие, пользователи не
вполне понимают, что между щелчком по
значку приложения и его запуском может
пройти несколько секунд, а то и десятков
секунд. Они начинают щелкать по значку,
запуская все новые копии. Между тем, при
работе с базами данных и во многих других
случаях иметь более одной копии не
только не нужно, но и вредно.

Идея
заключается в том, чтобы первая создаваемая
копия приложения захватывала некий,
ресурс, а все последующие при запуске
пытались сделать то же самое и в случае
неудачи завершались.

Пример
такого ресурса — общий блок в файле,
отображаемом в память. Поскольку этот
ресурс имеет имя, можно сделать его
уникальным именно для вашего приложения:

var
UniqueMapping : THandle;

FirstWindow
: THandle

;
begin

UniqueMapping
:= CreateFileMapping($ffffffff,

nil,
PAGE_READONLY, 0, 32,’MyMap’);

if
UniqueMapping = 0 then

begin
ShowMessage(SysErrorMessage(GetLastError)); Halt; end

else
if GetLastError = ERROR_ALREADY_EXISTS then

begin
FirstWindow := FindWindowEx(0, 0, TfmMain.ClassName, nil);

if
FirstWindowoO then SetForegroundWindow(FirstWindow}; Halt;
end;

//
Нет других копий — продолжение
Application.Initialize;

Примерно
такие строки нужно вставить в начало
текста проекта до создания форм.

Блок
совместно используемой памяти выделяется
в системном страничном файле (об этом
говорит первый параметр, равный -1, см.
описание функции

CreateFileMapping).
Его имя — муМар. Если при создании блока
будет получен код ошибки ERROR_ALREADY__EXISTS,
это свидетельствует о наличии работающей
копии приложения. В этом случае приложение
переключает фокус на главную форму
другого экземпляра и завершается; в
противном случае процесс инициализации
продолжается. ..»

Размещение на экране. Одно- и многостраничный
интерфейс. Модальные окна и фокус.
Панели, фреймы, деревья, графы, сети –
информационные модели визуального
отображения событийной парадигмы.
Концентрация и обобщенность размещения
интерфейса. Многостраничность и
многопроцессность интерфейса. Смена
изображений – действия в программе.
Активация элементов интерфейса и
использование фокуса. Модальность формы
– плюсы и минусы.

Технологии, обеспечивающие визуальное
проектирование интерфейса. Раскраска.
Библиотека графического интерфейса
операционных систем. Графические
библиотеки визуальных построителей
программ. Графически ориентированные
системы. Форматы графических файлов –
носителей графической информации.
Экспорт – импорт графических форматов.
Графические возможности микропроцессора
– типы данных, операции, видеосистема

Сменяемость окон и порядок их размещения.
Оконная парадигма и ее предистория.
Передний план и фон. Группировка окон.
Частичное и обобщенное отображение.
Активация оперативного.

Организация подсказок. MSWord– пример организации
подсказок. ПИК, как обучатель и стимулятор
роста интеллекта. Подсказки –
контекстность, конкретность, многослойность,
визуальность, переносимость,
настраиваимость, динамическая
(оперативная) тестируемость.

Требования эргономики и инженерной
психологии к интерфейсу. Не более 7
объектов в поле зрения, нейтрал раскраса,
раздражители внимания, понятная
(дружественная) мнемоника и визуализация,
максимум автоматического.

Интерфейсные объекты визуальных
дизайнеров и их использование при
построении интерфейса. Ветвь IInterfaceв дереве компонент. НаследникиIInterface.
Инструменты использованияIInterfaceи наследников.

Создание редактора свойств. Редакторы
компонент. Категории свойств. Пример
разработки инструмента с использованием
инструмента существующего..

Расширение оболочки Windows– мастер СОМ объектов, обработчики
перемещений, контекстного меню,
пиктограмм. Пример разработки инструмента
с использованием инструмента существующего.

Основная
литература:
5 осн. [
(4)Delphi7 –gl
5,6, 7,8]

Контрольные
вопросы:

  1. Какие элементы используются в стандартном
    интерфейсеWindows?

  2. Где расположены эти элементы?

  3. Где в программе м.б. размещены элементы
    интерфейса?

  4. Какие действия разработчика связаны
    с созданием интерфейса?

  5. Каков формат файлов графики стандартно
    используется в интерфейсеWindows?

  6. Что представляют собой объекты
    IInterfacе?

  7. Как группируются объекты реакции на
    события?

  8. Какие инструменты используются при
    создании собственных графических и
    мультимедийных

элементов интерфейса?

Программирование для Windows оболочки

http://blog.csdn.net/chchzh/article/details/2210729

Преамбула:

Я видел расширения для оболочек для Windows, как правило, делать какую-то работу непосредственно с оболочкой Windows API, в.

Поскольку операция оболочки требует некоторых более специализированных знаний, поэтому, большинство программистов в частности, использовании программного персонала интегрированной среды программирования

Расширение программирования Windows Shell не очень понимаю, но не хватает информации в этой области.

После того, как некоторые программы были сделаны, я чувствую, что расширенное программирование с помощью Windows Shell может сделать комбинацию программы и операционную систему более

Закрыть, кажется, что приложение было интегрировано в операционную систему. Глубокий вырез в процессе расширения инструмента программирования с помощью Windows Shell

Опыт важности Windows Shell Технических данных, для этого, по словам Дины Эспозито «Visual C ++ Windows Shell

«Программирование» синего цвета, собраны в следующий текст, обеспечивая небольшую помощь для тех, кто хочет программировать Windows Shell.

вступление

Добро пожаловать читать CV ++ для Windows Shell Programming, в этой книге вы узнаете, как расширить оболочку Windows, настроить его поведение и

Наследование применяется к оболочке Windows. Вы также найдете, как использовать и изменять его свойства для достижения максимальной производительности, а также назвать тех,

Метод отсутствия функций API Shell. Это не трудно программировать оболочки, но очень мало об этом является полным профилем.

 
эволюция системы

В Windows 95 и Windows NT 4.0, Microsoft делает оболочки оболочки оболочки оболочки оболочки оболочки оболочечной в в в в в и высоко подгоняет

SHELL и расширение пространства имен только множество масштабируемых айсбергов. Общее понимание программирования оболочки также включает в себя функцию API SHELL

И ключи реестра и т.д., они также могут превратить ваше приложение Win32.

Встроенный веб-браузер спутал разницу в локальных и удаленных объектов, который использует тот же стиль на рабочем столе, чтобы представить все.

Он может быть расширен для включения приложений и материалов пользователей. Встроенная новая оболочка Windows часть является ключевой частью этого процесса. Поэтому сегодня

Оболочка больше, чем просто COM, расширение и пользовательский интерфейс, а также содержит Интернет, динамический HTML и сценарий Windows. Shell стала

Точка коллекции, содержащая большое количество технологий клиента. Каждый разработанный для Windows код программист, будет актуальным и глубоко в ближайшее время

В доступе рутина исследовать внутренние особенности оболочки Windows. Эта книга содержит все функции API Детальное описание, раскрывающие ОШИБКИ и нет

Описание характеристик информации. Он выходит во внутренний мир детектора, выявить блестящие вещи, такие как крючки, реестра, браузер помощь

Объект, расширение оболочки, расширение пространства имен и веб-наблюдение. Он также отметил расширение среды скрипта для Windows и оболочки объектов сценария.

Эта книга настраивается для профессиональных разработчиков, существуют три основные цели:

Обеспечить толкование существующих и информация бедности SHELL API

Дайте новую концепцию приложения

Показать новые функции о IE4.0, активном рабочем столе, а также Windows 98 и как эти новые возможности адаптации к корпусу существующего.

сфера книги

В этой книге, мы должны ответить на следующие общие проблемы.

Что такое оболочка апи и как его использовать?

Как использовать реестр, чтобы настроить свою оболочку Windows

Как я могу создать специальный каталог, как «корзина» и «Мой портфель»

Какие различные методы вставляются в адресное пространство детектора

Как обрабатывать иконки, бары задачи, и «корзины»

Что такое среда скрипт для Windows, как я могу его использовать?

Что является объектом сценария оболочки и браузер помощи объекта

Как я могу добиться поддержки документа оболочки для моего приложения?

Как я могу настроить мой документ?

Как использовать COM и ATL в Shell и пространств имен расширений, чтобы изменить поведение Shell

Как устранить ошибки в расширении оболочки

Интерпретировать принцип создания успешной интеграции оболочки и технологию, необходимую

Как использовать динамические HTML клиентов папку?

Каждый программирования проблемы Shell, используя фактические процедуры объяснил, что это пример программы по VC ++ 6.0 и ATL3.0 письменной форме. Эта книга имеет

Некоторые более интересные процедуры:

Подкласс кнопки «Пуск»

Создание и установка новых усовершенствованных процессоров быстрого доступа

Новые объекты, работающие со средой сценариев Windows,

Назначение различных иконок и растровых файлов для расширений оболочки на основе управления размером платы

Кнопка в детекторе и построить новую папку

Отображение открытого окна в качестве узла в детекторе

 
Технические препараты

Подготовьте компьютер под управлением Windows98, Windows95 или Windows NT 4.0 (с ServicePack4.0), вам не нужно его сказать.

Обратите особое внимание на некоторые процедуры требуют, чтобы вы установили IE4.0 или выше.

Код написан VC ++ 6.0 и ATL3.0, и могут быть ошибки в CV ++ 5.0. Книга также использует среду скрипта Windows и IE4.01

Окружающая среда написала несколько примеров.

 
Используемый метод

Различные текстовые шашки используются в книгах для различения различной информации. Вот несколько примеров и их значение.

В коробке есть важные инструкции, они напрямую о контексте.

Другая информация выглядит следующим образом в тексте.

Важный текст дает черное тело

Текст появляется в горе экрана, такая как выбор меню, тот же шрифт, отображаемый на реальном экране

Кнопки на клавиатуре, такие как CRTL и удалить

Все имена файлов имеют pidl.cpp

Shbrowseforfolder () стиль

Новый, важный и связанный с ними Код, связанный с текущими вопросами обсуждения, имеет следующую форму:

void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)

{

HWND hwndOK = GetDlgItem(g_hwndDlg, IDOK);

// Simulate the Close button being pressed

if(IsWindowEnabled(hwndOK))

PostMessage(g_hwndDlg, WM_COMMAND, IDCANCEL, 0);

}

========

Программирование Windows Shell Programming Глава 1

http://blog.csdn.net/chchzh/article/details/2211475

Какова первая глава Windows Shell?

Хорошее определение корпуса операционной системы заключается в том, что это пользовательский интерфейс, предоставляемый системой, который позволяет пользователям выполнять публичные задачи, такие как доступ

Файловая система, Исполнитель экспорта, изменение системных настроек и т. Д. MS-DOS имеет командующую компанию, воспроизводимую эту роль. Но окна

Уже есть графическая интерфейсная среда, а его корпус неизбежно неизбежно является графическим способом. Перед Windows95, окна по умолчанию

Shell — это менеджер программы.

Manager Program — центральная консоль, которую вы можете запустить приложение, перегруппирование и значки реструктуризации и выполнять новые задачи.

Другими словами, менеджер программы управляет всеми программами, которые сосредоточены в Windows Big Smbrollas в качестве приглашения его имени. Теперь переписка

Менеджер является файловым менеджером, который является инструментом, предназначенным для поддержания файловой системы.

С появлением Windows95 детектор заменяет эти два старых инструмента и интегрирует функции двух. Если вам нравится, вы

Еще можно найти, чтобы файловый менеджер по-прежнему глубоко скрыт в системном каталоге Windows. Тем не менее, потому что пользовательских друзей чувства бедны, чем его преемник

Это уже очень используется сегодня.

Концепция общих ошибок считает, что детектор — это программа, когда вам нужно нажать «Мой компьютер» или щелкните правой кнопкой мыши »

«Кнопка для просмотра файловой системы, эта программа запускается. На самом деле, детектор всегда начинается и работает, от загрузки, пока вы

Закрыть компьютер. Интуиция — «детектор» на самом деле является окном под новой концепцией. Детектор является исполняемым модулем (Explorer.exe)

Он реализует функцию оболочки Windows.

В этой главе это в основном, в основном представить внешний корпус и детектор, точнее

Компонентная часть оболочки

Структура детектора

 
Компонентная часть оболочки

Shell состоит из многих разных частей, и теперь мы начинаем с наиболее очевидных настольных и задач полос. Из концепции, рабочий стол все

Родительский объект объекта Windows Shell, то есть объект хоста. Для реализации рабочий стол — это специальное окно для класса определения определения системы.

Назван # 32769) И это окно предка всех окон. Окно верхнего уровня, которое экспортировало приложения, как правило, является подсчетом рабочего стола.

В этих подмасах есть интересное дерево окна дерево, а его корня — это «менеджер программы».

Вы можете использовать инструмент CV ++ Spy ++, чтобы проверить окно, открытое в стеке окна.

      
Менеджер программы поддерживает совместимость. Вы можете увидеть на рисунке, его структуру пакета: прямой подчиненный менеджер программы является жизнью

Shelldll Defewiew Window Class, это окно содержит объект наблюдения по умолчанию, на самом деле это окно отвечает за перечисление стандартных файлов

Содержимое зажима, он всегда экспортируется из элемента управления ListView, который является универсальным системным управлением. Окно Shelldll Defview содержит один

ListView (класс по имени syslistview32) и управление заголовком (класс с именем sysheader32), элемент управления заголовками используется только для ListView

Сообщить о наблюдении.

С выпуском Active Desktop и Windows98 IE4.0 наблюдаемый объект по умолчанию уже имеет изменения в зависимости от определенных возможностей браузера.

изменение. В следующей главе мы обсудим эти наблюдения и их изменения.

 
Руководитель программы

Как и предыдущее упомянуть, окно менеджера программы зарезервировано для совместимости. Это просто демонстрирует приложение окна от 16 до 32

Эволюционный процесс бита. В среде Win16 единственный метод связи с оболочкой осуществляется через динамические обмена данными (DDE). Этот уровень кода

Он все еще поддерживается в Windows95 или даже Windows 98. Почему? Для совместимости.

Об интерфейсе DDE становится подробным описанием оболочки, рекомендуется проверить последнюю букву в Интернете CLIVESDK.

интерес. DDE — более старая технология, Microsoft имеет большое количество информации.

 
Строка задач

Основные компоненты Windows Shell является панель задач, на самом деле это окно принадлежит процессу зонда. Всякий раз, когда вам нужно до конца

Когда процесс зонда, приведет к тому, чтобы панель задач исчезать и появляться. Каждый раз, когда он объявился, он зарегистрирован с другим

Новое окно HWND из. Таким образом, это ссылка с точки зрения, вам не нужно держать HWND этого окна. Панель задач также у каждого есть «Пуск» по

Кнопки окна, элементы управления часы и есть подобная кнопка в трее области, представляют запущенное приложение.

Как практически на панели задач окна, любое окно может быть сделано на операцию можно выполнить на нем, например, перемещение, сокрытие, и как подкласс.

В главе 7 мы расскажем, как подклассы панель задач и кнопку «Пуск». Как скрыть панель задач можно найти в главе 9 и скомпилированы

Restart Shell. Эта последняя характеристика достигается при компиляции и расширение пространства имен оболочки полезно.

 
рабочий стол

Если вам интересно, ярлык на рабочем столе, откуда она и кто принадлежит, честно говоря, я думаю, что в начале этого детектора модуля жеребьевке

Некоторые значки, настройка записи, цвет, статус и так далее пользователь. Этот модуль может рисовать открыть набор обоев пользователя на фоне рабочего стола.

Desktop не работает таким образом, наоборот, как ярлык отображается в ListView Коммон. Конечно, это

ListView с необычной вариации, но это действительно ListView, так что это не трудно обрабатываются из сообщения

, Подпрограмма будет дано в главе 9 будет описано ниже.

 
Структура детектора

Детектор представляет собой системное приложение играет роль в жилищном строительстве. Когда дело доходит до расширений оболочки, мы говорим о том, чтобы обнаружить

Воспринимаемого заряженный блок кода выполняется в последнюю очередь.

Зонд можно рассматривать как окно миниатюрной среды разработки. Представьте себе: у него есть свои собственные функции и диалоговые окна, разрешено писать

Специальный интегрированный с существующими приложениями системы; толерантными приложениями и документами. Он даже может объяснить, какую-либо деятельность совместимого языка сценариев

Script (VBScript, JScript, Perl и т.д.). Книга будет включать в себя все эти функции.

 
Расширенная точка входа

Выпущенные вместе с менеджером Windows3.1 файла имеет очень хорошие свойства, как только недостаточно используемые, например: он может загрузить DLL во время выполнения

Выполнение специальных функций, таких как прототип был зарегистрирован. Другими словами, есть немного в этом ресурсе, который является код сам по себе может знать для определенных видов деятельности

Это выполняется пользователем. Другими словами, файловый менеджер поддерживает поведение расширения при выполнении определенных видов деятельности, чтобы найти и загрузить регистрацию расширения

И запустить его.

Мы видим, в задней части корпуса детектора и пространство имен расширений на самом деле имеют один и тот же принцип. Совершенно иные детали

Реализация. Диспетчер файлов для загрузки всей обычной функции DLL, имеющей предопределенные детекторы прототипа более стандартизированный процесс. особенно

Какой он использует COM-интерфейс (и может рассматриваться в качестве заранее определенного набора фиксированной функции прототипа) и в процессе, по существу, серверы (DLL)

Конечно, в интерфейсе COM и серверный процесс является более сложным, чем набор функций и DLL, но это также делает процесс детектора, чем старый процесс на основе DLL более

Технические характеристики и мощные.

 
Удлинитель на детекторе

В среде детектора, существуют два основных типа расширений: Расширения пространства имен и расширенное жилье. Судя из названия немного запутанным

Детектор является оболочкой для Windows, поэтому эти два типа расширений может быть расширен в качестве оболочки. Другими словами, корпус и расширение пространства имен

Оба расширили возможности детектора выставки. Но есть некоторые различия между ними.

Расширение корпуса добавляется к клиенту на поведении всех файлов данного типа, данный типа отображения документа в соответствии с требованиями заказчика

Наблюдение зонда. Таким образом, вы можете назвать это «наблюдается расширение оболочки.» Поведение клиентов, таких как перетаскивание правой кнопкой мыши контекстное меню, окрашенная

Значок системы или диалоговое окно Display Properties, и т.д. инициируется ряд специальных мероприятий. Вы можете определить специальную программу, процессор этих событий, например,

Вы можете определить, значок, отображаемый в данных файлах .BMP, а также страницу предварительного просмотра в диалоговом окне свойств для всех метафайл Windows, или даже

Добавить исполняемую функцию в контекстном меню. Рутинное будет дано пятнадцать глав.

Пространство имен расширения в двух формах, в зависимости от способа подключения. Если подключить расширение типа файла имен, несмотря на то,

Комплексный код поддержки, который функционально эквивалентен прежнему расширенного контекстного меню. Однако, если вы используете пространство имен папку расширения подключения файла, который

Папки будет папка клиента, ваш код будет определять содержание значок папки отображается детекторные, подпапки, сортировка, выкл

Объединенное меню.

 
Почему Shell должна скомпилирован

Это очень разумно, простой ответ заключается в том, чтобы сделать наш корень приложения и полнее. Но этот ответ слишком много риторики

Мы делаем это, чтобы сделать наши модули и системы интегрированы друг с другом, или более автоматизирован.

 
Эта книга

Есть два способа программирования корпуса, с помощью функции API и использования COM-интерфейсов. Оба метода не являются ни независимыми друг от друга или перекрывают друг друга

Они два разных направления и две различные области, которые мы прорабатываются в следующей главе. Давайте теперь непосредственно просматривать

На содержание глав.

Вы знаете программирование Shell требует использования функций API и COM-интерфейсы, функции API позволяют получить доступ к основным функциям компании Shell, например,

Операции с файлами, просматривать папки, выполнение программы, иконки для обработки и ярлыки. Если вы хотите, чтобы улучшить и усовершенствовать основное поведение Shell,

Метод COM клиент идет к сердцу расширений Shell.

Эта книга сначала дает все интерпретации всех функций API и дополнительно исследовать принцип функции, внедрения информации и

Ошибки. Обычно моя цель состоит в том, чтобы прояснить все конфликты с которыми вы столкнулись в этой информации. Глава III Глава 9 Возьмите специальную группу APIS

Типичная операция оболочки включена в третью главу, а копия файла участвует.

Переместить, удалить и переименовать операцию. Четвертая глава раскрывает загадочную функцию hgetfileinfo (), и система предоставляет файл (атрибут, значок)

Системная информация и информация оболочки типа и отображаемого имени). Глава 5 объясняет процесс наложения внутренней организации папки, включая параметры,

Просмотрите и сделайте специальные папки, такие как избранные и отправьте.

Ярлыки и свойства вводятся в главе 6, которая будет введена для установления и разрешения ярлыков и часто используемых полей. Глава VII официально введена

Введите адресное пространство детектора и обсудите вопросы настройки с другой точки зрения: какова ваша безопасность в случае, когда детектор неизвестен?

Отказ Особенно мы показываем вам кнопку «Пуск» и разные меню. Как только вы сделали это, у вас есть это.

Полностью контролирует способность системы Windows. В остальных восьмых и девятых главах мы расскажем расширительную, иконку и бруски задачи, мы

Объяснит, как программировать новую кнопку на панель задач.

Вторая часть этой книги основана на функции зонда, которая требует интерфейса COM. Но до двенадцатой главы мы не вовлечены в связи.

Знание, середина двух глав, как мост функции оболочки и интерфейса детектора. Глава 10 содержит недавно обновленные функции Windows SDK. десятый

Одна глава дает обзор объекта Shell, такой как «мой портфель», «Панель управления» и «принтеры», а также обзор папки клиента.

читать. В этой главе другие программы используют другие объекты Shell и Runtll32 и пояснения всех командных строк детектора.

Глава 12 Знакомство с объектной модели Shell, первый посвящен двигаться подмножество функции API к соответствующему COM-интерфейса, эта функция является наиболее

Меньше требований к установке «Active Desktop» в системе. Интересно, что эта модель объекта позволяет получить доступ к определенным функциям системы (большинство системы

Чат).

Глава 13 Внедряет среду сценариев Windows, это двигатель выполнения, который выполняет файл пакет Windows. Технически, это не

Сущность оболочки, но она имеет важные отношения с оболочкой. среда сценария Windows, показывает объектную модель, которая позволяет использовать

Vbscript, JScript и т.д. любых программ написания языка сценариев. Я расширю эту модель, присоединившись к полезным новым объектам.

Глава 14 фокусируется на руководящих вас от применения и причин оболочки и расширения пространства имен. Я раскрою, что фактическая интеграция оболочки должна быть

Что является лучшим способом, она использует то, что это лучший способ расширения оболочки интегрировано с модулем приложений и системной оболочкой. Глава 15 объясняет, как написать один

Расширение оболочки, чтобы настроить связанное меню, значок и атрибуты и как устранить неполадки. Шестнадцатая глава кратко содержание расширения пространства имен, и

Включите пример, как добавить наблюдение дерева, которое можно расширить узлы к детектору и продемонстрировать текущее окно в виде папки.

Процесс стека.

 
резюме

В этой главе мы описываем вещи, которые планируют в будущих главах, особенно мы пытаемся объяснить:

ОБОЛОЧКА природа и структура

Различия между каждой версией оболочки

========

Программирование оболочки Windows Глава 2

http://blog.csdn.net/chchzh/article/details/2222622

Глава 2 SHELL Структура

«Программирование оболочки» имеет большое количество функций API и COM интерфейсы. Широкий ассортимент «командных» наборов позволяет использовать разные вечеринки

Оболочка Windows запрограммирована. Функции и интерфейсы не эквивалентны одной и той же функции, что сторнируется, они находятся в разных логистики

Различные функции доступны на архитектуре.

Функция API содержит основные операции, которые пользователи хотят выполнить на объекте оболочки, такие как файлы и папки. Интерфейс COM дан

Расширенное улучшение, даже возможность настроить различные объекты факторов, в том числе стандартное поведение Shell. Используйте метод критически ориентированный на функцию и объект

Группа даст нам возможность наблюдать за оболочкой, поэтому мы все еще можем думать об этом как об этом как о атрибуте и методе.

Слон. В этой главе мы будем работать, чтобы разделить группы, которые отличать, что каждая функция и интерфейс принадлежит. Это поможет нам от много работы

Найдите интерфейс программирования Shell в фрагментах.

В этой главе, он будет включать в себя:

Мы используем определение, используемое в этой книге

ОБОЛОЧКА API-функция пакетной функции

Функциональная группа интерфейсов COM, реализованных оболочкой и его компонентами для отъема

Как структура оболочки развивалась на рабочем столе импортированной активности

И, наконец, вы сможете лучше понять сферу знаний этой книги, и в качестве программиста оболочки, вы будете в состоянии очистить, которые работают в книге

Это может быть доступно.

 
Модуль оболочки

На самом деле, мы не можем сказать, что оболочка Windows ориентирована на объект. Есть некоторые «объект» для просмотра структуры.

Определите это. Эти объекты также имеют те же характеристики, как «атрибут», и некоторые виды деятельности выполняются как метод. Но они зависят от функции API

Типичный объект — это папка.

Если оболочка не объектно-ориентированный, он никогда не будет иметь полностью совместимую объектную модель. Мы можем представить себе внешний вид

Архитектура слоистого объекта. Другими словами, существует множество объектов, который работает, как способ, описанный ниже.

                     
В основном, оболочка состоит из папки, папка представляет собой контейнер, содержащий вложенные элементы, включая вложенные папки, которые, как правило,

запись Folder. Корневая папка называется «рабочий стол», а его дети включают в себя «мой компьютер», «онлайн сосед», «рециркуляция станции», и

Другие возможные элементы, все эти папки называются SHELL пространств имен.

 
Пространство имен Shell,

Концептуально, папка похожа на каталог файловой системы, но это не обязательно связывается с фактическим физическим каталогом, например,

Если он не имеет состояния, это называется виртуальной папкой. Мы можем различать два основных папок следующим образом: обычные папки (жизнь)

Названная папка или каталог) и папка клиента. Природа, включенная в папке типа файла является файлом, его свойство имен, классы

Тип, размер, окончательная дата модификации и т.д. Продукты, содержащие под любой другой папке может быть файл — как правило, используют другие наборы символов расширения

— Но она также может быть совершенно разными, например, принтеры или сетевые узлы.

 
папка

Как это реализация папки? Папка на самом деле оболочка объекта, его поведение кодируется в COM-модуль, в ОС Windows

Shell предоставляет открытый интерфейс. По связи, папка может сообщить оболочке, как проектировать его содержание, какой вид значка используется,

Какой текст используется для описания, например, «Мой компьютер» выглядит как папка. Он имеет кодовый слой ощутить все имеющиеся на компьютере.

Привод и наблюдение каждого диска на каждый диск до детектора.

Каждая отдельная папка имеет различные типы иерархического кода, чтобы обеспечить различные модели поведения, для папок типов файлов, поведение

Это сканирование файловой системы, восстановить файлы и вложенные папки, и выводит их через управление списком. И запись папки принтера, что встречается

И установлен принтер и отображать иконку для каждого. Вы можете создать любой тип виртуальной папки с любым поведением

Отказ Папка типа файла (например, каталог) только один из них.

Для папок типа нефайловых, оболочка является относительно небольшой, и только некоторые инструкций в специальной папке. На самом деле Windows,

Оболочка предоставляется по умолчанию, что папка клиента разница из папки типа файла:

Может содержать файлы и другие объекты

Можно представить различные наблюдения для содержания

Вы можете быть связаны с физическим каталогом.

Она является частью определения системы, которая предусматривает специальную функцию, установленную SDK.

 
Специальный список папок можно найти в данных Win32 SDK и пятой главе ниже. Так же, как я уже говорил, специальная папка

Существует особый тип папки для вашего COM модуля, чтобы обеспечить поведение. Так как COM-модуль, является предпосылкой, что новый узел добавляется к пространству имен оболочки,

Это называется расширением пространства имен.

Специальные папки позволяют пользователям информации о системе доступа в соответствующий интерфейс. Другими словами, в большинстве случаев, этот файл

Содержимое предоставляемые папки типичного типа файла есть несколько меньше мест. Конечно, точная степень зависит от папки

тип.

                  
Как и обычные папки, специальные папки могут также содержать файлы. Однако, как правило, проявляется в несколько ином виде, показывая различные специальные

Поздно. Поэтому специальные папки дают разные значения для файлов, а не относиться к ним как обычным субъектам файловой системы (если не

Таким образом, это не особый). Например, «Корзина» содержит нормальные и подразумеваемые файлы, так как эта папка хочет, чтобы отобразить ток

Логотип представляет собой список удаленных файлов, так что отображается в передней части исходной функции положения и удаление даты.

Большинство (не все) специальные папки прикрепляются к физическому каталогу на диске, который является нормальным в нормальных условиях.

Запись, его содержание всей информации, которая должна отображаться с наиболее подходящим способом.

Для точки зрения, большинство специальных папок требуется каталог для хранения своих данных. Этот каталог может быть назначен

Anywhere диска и ссылки на поддержку папок и оболочки — эта специальная папка в пространстве имен. каталог

Содержание не должно отображаться в виде списка файлов. В отличии от этого, код соответствующей папки может быть объяснена и отображается в форме, которая лучше всего подходит для его роли.

Папка Это имеет два важных понятия, с чем-то, что содержит что возможности, файл объектов и PIDLs, это мы будем

В следующих разделах.

 
объект File

Объект файла представляет собой элемент включены в обычной папке — файл, запись, блок памяти и подключенные устройства. «Запись папки

«» Элементы Папка и „Object File“ Эти термины эквивалентны. Если папка папка типа файла, объект файла

Это файл. Так в «файл» здесь немного особенная, чем «объект файла», поскольку он точно представляет один из файловой системы.

организация. Файл представляет собой объектный файл, но объект файла не обязательно файл.

Существует чувствительный вопрос, который появляется в понятии общей папки и папки, я в пространстве имен оболочки.

Как мы можем безопасно и только те элементы из них. Если оболочка согласуется с файловой системой (так же, как Windows 3.x),

Полное название произведения может гарантировать уникальность. Невозможно иметь две части файла с тем же путем и именем. Тем не менее, когда папка

Когда каталог становится все более распространенным, деталь отличает это нуждается в более общих методов.

 
PIDLs

PIDL представляет собой структуру данных, которая однозначно идентифицирует один метод элемента, включенного в папку. PIDL-идентификатор списка

Указатель на список идентификаторов — это более распространенный метод, чем полное имя файла, а не только в папке

И уникальность этого пункта гарантируется во всем пространстве имен оболочки. Что еще более важно, он может прозрачно обрабатывать файлы и файловые объекты. Для

Понимание структуры и роли PIDLS, давайте проанализируем его бинарную структуру и сравнить его с именами путей заменены.

Полное именем является строкой, то строка с очень специальным форматом, серия substrs, каждая

Оба представляет собой слой на уровне файловой системы, есть имя диска, то имя каталога, имя файла, и, наконец, расширение, они

Оба отделены друг от друга обратной линии. Полное имя вы знаете, чтобы указать на эти соединяемых элементов — указывает на строку. От отъезда

Читайте, вы можете думать об этом как структура массива, каждый элемент представляет собой имя пути элемента. Быть

  
 
На рисунке выше показана взаимосвязь между именем пути и PIDL, и он также дает представление о списке идентификаторов в структуре памяти. программирование

Чтобы упомянуть, PIDL реализуется по типу LPITEMIDList, который является указателем для ITEMIDLIST структуры.

typedef struct _ITEMIDLIST

{

SHITEMID mkid;

} ITEMIDLIST, *LPITEMIDLIST;

Объект, составляющий путь в середине отображается на идентификатор проекта PIDL. Они существуют во всей структуре SHITEMID.

typedef struct _SHITEMID

{

USHORT cb;

BYTE abID[1];

} SHITEMID, *LPSHITEMID;

Первые два байта структуры указывают размер идентификатора элемента — то есть, данные связанного с ним элемента и число байтов, занимаемая данными указано.

Значение CB должен содержать свой собственный размер. Соответствующий путь к файлу, CB должна быть длиной диска или каталога без знака плюс

КОРОТКИЙ тип переменной длиной. Тогда первый байт этой структуры данных.

Обязательно помните, что PIDL является «плоскость» структура, которая не включает в себя указатель. Все данные формирования PIDL должны быть значительно агрегируются к одному

Пуск, а не через указатель. То есть, мы не можем использовать типичную схему структуры цепи с точкой до последнего члена элемента.

Следующий элемент в цепочке. Еще один момент, так же, как это видно на рисунке, адрес следующего элемента в цепи может быть добавлен к текущему CB.

Объект SHITEMID вычисляется. Это дизайн указано, поэтому SHITEMIDS, что требуется для подключения к пространству.

Определение конструктора PIDLS код, который обеспечивает реализацию поведения папки. Эти код должен также определить, какие данные используются

Для представления элемента идентификатора. Например, предположим, что вы хотите реализовать папку, откройте реестр Windows, «подпапки

«Он должен быть ключ реестра» объект файла «должен быть значение реестра. В этой папке, возможный метод каждого элемента должен быть сделан

Используйте относящееся имя ключа. Здесь мы можем увидеть, как PIDL использует тот же формат схему, как и в предыдущем представлении. Уведомление

HKEY_CLASSES_ROOT длинный набор, поэтому он имеет четыре байта плюс два байта неподписанных коротких целых чисел.

            
Проект связанного списка представляет собой путь след и корень из пространства имен в папку конкретной. Этот идентификатор собирается в цепочке.

Это иллюстрирует способ уникальной идентификации элемента оболочки. Убедитесь в том, что два идентификатора проекта непрерывно назначаются в памяти, чтобы быть папка пары

Обязанности соответствующего кода. Хотя имя путь похож на PIDLS, они не эквивалентности, они не могут взаимодействовать, они разные данные

состав.

 
наблюдение SHELL

Содержание любой папки отображается в детекторе Windows, через оболочку объекта вызова. Каждая папка

Его собственный объект наблюдения оболочки определяется, и все задачи, связанные с этим интерфейсом пользователя назначены к этому объекту. Для файлов

Тип папки Shell объекта наблюдения список наблюдаемых элементов управления, который является именем файла и подпапки. По умолчанию наблюдение оболочки

Значок выделить значки, отображаемые имена и имена типов для каждого файла, когда он вызывается при обработке файла.

Есть несколько способов, чтобы определить, в зависимости от характера файла запроса. Обычно используют сам значок отображения значка файла

(.Ico), файл программы отображается один значок определяется в его ресурсе. Если значок не определен, отображается по умолчанию. Для

Есть другие файлы и оболочек обычно используются иконки, определенных файл домашнего класса. Однако, такое поведение может быть принято как следующее раскрывается.

Победа.

Во всей среде оболочки, то файлы пакеты группы, указанные в соответствии с расширением файла, который основан на типе типа

Сбор обычно называют как класс файла. Это связано с иконкой и строки дескриптора, который отображается в детекторе Windows.

Колонка типа на тонкой информационном окне. Однако, чтобы заменить их, то указанные потребности класса файл, который будет зарегистрирован в реестре, и оболочка будет читать там.

Информация Из типа и значок.

После того, как файл класс определен, вы можете написать код, чтобы влиять и корректировать оболочки ответ на некоторые события, которые происходят в классе конкретных файлов.

Поведение по умолчанию, который включает в себя рисунок значок файла, всплывает соответствующее меню и диалоговое окно свойств дисплея и тому подобное. Определяя расширение оболочки, вы

Вы можете динамически определить, что эти события должны делать. Например, вы можете добавить новый элемент в соответствующем меню, а точка для обработки пользователя.

Хит и динамически определить отображение значка, основываясь на каждый файл.

крюк оболочки

При нормальных обстоятельствах, расширение оболочки можно рассматривать как крючок, он устанавливается во всей оболочке. В Win32 крючок является периодом

Применяя определенный код, система обратных вызовов этого код, когда происходит событие. Существует много разных типов крючков, и их приложения также очень широки.

Есть некоторые только влияющие только на приложение, которое устанавливает их приложения, в то время как другие влияют на приложение всех систем.

Это типичный пример хук клавиатуры, что позволяет получить клавиатуру перед отправкой соответствующего сообщения в окне приложения.

Информация. Примеры других крючков, такие как деятельность мыши (мобильный, клик), управление окнами (создание, разрушительная, активность), и обработка сообщений. Даже

Для получения дополнительной информации см. Данные Win32 SDK.

С точкой зрения программиста, крючком является функцией обратного вызова с фиксированными и предопределенными грамматиками, как функция обратного вызова, система базовым

Назовите это в известном прототипе. Расширение оболочки — это интерфейс COM, а не функция обратного вызова, но принцип за ним одинаково, оба позволяют

Вы указываете часть кода будет выполняться для обработки некоторых предопределенных действий.

Этот раздел особенно отмечается в крюке Windows. Настраивая локальные крючки, вы можете только захватывать вещи, которые происходят внутри связанных приложений.

Часть. Однако установка полного крючка приведет к подключению события, которое произошло в любом запущенном приложении. Настройка полного крючка означает ваше приложение

Код, его можно выполнить в других связанных с ним процессах. На самом деле используйте крючки для завершения пограничной границы Win32 и генерации инъекций

Код для других процессов является самым простым способом. Это также единственный способ работы на всех платформах.

 
Оболочное адресное пространство

Другой процесс, который вводится в ассоциацию, важно, потому что он позволяет получить доступ к другому процессу без публичных объектов, эту пару

Программирование оболочки особенно важно. Когда вы успешно поместить код в адресное пространство оболочки, вы можете запросить интерфейс оболочки и изменить пользователя.

Рот, даже заменил кнопку «Пуск».

Весь крючок — это метод, в котором ваш код работает в адресном пространстве оболочки, но более мощные и более гибкие механизмы

Укажите объект справки браузера — объект COM, детектор и то есть автоматически загружается при запуске главного окна.

 
Памятная память Дистрибьютор

Когда вы используете оболочку, вы быстро обратитесь к распределению памяти, и оболочка предоставляет дозатор хранения, этот пакет

Услуга интерфейса IMALLOC может использоваться вместо новых или GlobalAlloc ().

Чтобы получить ссылку на этот объект, вы должны использовать SHGETMALLOC (). Это не новый указатель на интерфейс imalloc —

Возвращается функцией CoGetMalloc () — но это ссылка на объект IMalloc с помощью системной оболочки. Используйте этот указатель, вы можете безопасно

Выпуск выделяется оболочкой и делает оболочку выпустить эту память. Это может быть немного незнакомым, но в программировании оболочки это

хорошие привычки.

 
Shell Pails Bar

Окно таблицы задач как известная часть пользовательского интерфейса Windows, только потому, что он содержит кнопку «Пуск». Недействительный

И мы называем это «панелью задачи Windows», потому что на самом деле это специальный случай серии Window, называемый «прикладным настольным компьютером».

С ударом, лучшая иллюстрация — это ярлык Office97. Существует специальная функция и набор сообщений, связанный с панелью инструментов настольных компьютеров, но

Интересно, что только небольшое количество функций и сообщений влияют на панель задач Windows. Поэтому, даже если информация не понятна, строка задач системы и таблица

Поверхностная панель инструментов все еще разные объекты.

Другая ошибка на панели задач заключается в том, что она содержит кнопки для всех прогонов, но есть две причины, которые это не

настоящий:

Не все запущенные приложения отображаются на панелях задач

Как кнопка, единственная из панелей задач — кнопка «Пуск»

Независимо от того, верили ли оно, поскольку набор кнопок на самом деле является элементом управления вкладкой, это просто стиль кнопки специального класса.

Строки задач играют роль в плате управления системой, чтобы позволить вам получить доступ ко всем запущенным. Во многих случаях мы надеемся

Может ограничить функцию панели задач — это типичное требование, которое работает на публичных ПК, где вы не хотите, чтобы пользователи запустили его.

Его программа или просматривать файловую систему. Win32 API не предоставляет богатую функцию для работы баров задачи, но мы будем стараться, чтобы в главе 9

Некоторые средства правовой защиты за это.

 
Функция API оболочки

Ссылка оболочки раздел библиотеки MSDN снабженным 6.0 списки более чем 100 функций VC ++, однако, большинство из них только

Выручка в очень особенном поле, иногда ощущается как граница Windows Shell — вот особая информация о анализе документа и экрана

Рутины защиты занавесов.

В этой книге вы не можете найти подробное описание каждой функции, однако мы можем сосредоточиться на файлах и файлах.

Основная функция и попыталась уточнить их подтвержденную информацию. Для того, чтобы помочь им в дальнейшем КЛАССИФИЦИРУЙТЕ, мы разделим их пять

Разные функции.

 
Группа

Функция

Общая функция Windows

 
Внутренняя функция SHELL

 
 
Функция задач

 
функция файла

 
Функция папки

Рекомендуемая защита экрана, панель управления сценарий, интерактивная справка, и оболочка сопротивление (не OLE перетаскивания)

Доступ к функции адресного пространства детектора, получить функцию распределения памяти оболочки, экспортировать функцию исполняемой программы, и как изменяются пользовательский интерфейс

Различные функции.

Рекомендуемые функции домена подноса и функция с панелью задач Windows

Функция файла Операция, они выполняют системные действия, такие как «копия», «мобильный», «удалить» и «получить информацию» и другие операции, а также добавить

Добавить файлы в специальные системные папки, такие как «последнего документа» и т.д.

Управление функции папки, использовать эти функции, вы можете просматривать папку, найдите путь к системной папке, и открыть настройки папки.

Согласно этой структуре пакета, можно заметить, что некоторые функции, как часть интерфейса программирования оболочки не указаны явно, но они по-прежнему

Стоит появляться в этой таблице.

 
Группа

Функция

функция Иконка

функция окружающей среды

Shell Легкий API функции

Функция для извлечения иконок из файлов исполнения

Ручка функция переменных окружения

Легко получить доступ к функции реестра, чтение и функция реестра записи, функции имени пути процесса и обработки строковых функции.

 
В частности, некоторые значки функций и переменные окружения в файле заголовок shellapi.h, мы здесь, чтобы показать их главные

Причина. Так же, как легкий API функция SHELL (подробно в главе 10), мы говорим, что эти функции могут быть размещены в любом

В, однако, они имеют специальные цели для программирования Shell. Некоторые буквы, определенные в этом методе классификации в таблице следующего раздела

количество. Причина заключается в том, чтобы лучше понять концепцию функциональных операций, и предоставить вам быстрое нахождение функций.

 
Общая функция Windows

Как указывает название, эти функции только немного вовлечен в Windows Shell, в большинстве случаев, он

Все они поступают непосредственно из API в Windows 3.x — они только выполнять операции, такие как помощь файлы и перетащить все эти функции хорошо поддерживаются.

32-разрядная версия оболочки.

 
функция

описывать

DragAcceptFiles()

Тег позволяет окно распознавать операцию перетаскивания.

DragFinish()

Освободить память, выделенную из списка SHELL

DragQueryFile()

Отвар имени файла из блока памяти, выделенный из оболочки

DragQueryPoint()

Получить точку, где произошло лобовое сопротивление

CPlApplet()

Основная программа окна Панели управления скриптом

GetMenuContextHelpId()

Возвращает идентификатор справки, связанный с данным меню

GetWindowContextHelpId()

Возвращает идентификатор справки, связанный с данным окном

SetMenuContextHelpId()

Установите идентификатор справки, связанный с данным меню

SetWindowContextHelpId()

Установите идентификатор справки, связанный с данным окном

WinHelp()

Открыть файл справки

ShellAbout()

Показать «О информационном окне Дефолта и Specific Кастомизации

 
Внутренняя функция SHELL

Такие функции включают в себя оболочку, лежащую в основе работы функции, и позволяют ввести в адресном пространстве оболочки, и вы можете работать с одной стороны.

И получить функцию пространства доступа с начала года.

 
функция

описывать

ShellExecute()

Выполнение специальных операций на указанный файл

ShellExecuteEx()

С одной и той же функцией, есть более широкий выбор

SHChangeNotify()

С помощью этой функции программы, вы можете позволить оболочкам знать, какие изменения, и попросите его обновить информацию, которую он защищает.

SHGetInstanceExplorer()

указатель на интерфейс IUnknown Вернуться Detector

SHGetMalloc()

Возвращает указатель на дозатор для хранения оболочки

SHLoadInProc()

Загрузить указанный объект COM на адрес детектора пространства

 
Функция задач

Оболочка Windows не определяет, сколько операции задачи баров, поэтому барам задачи управления часто нужны делать сам.

Ибо, однако, есть две функции, связанные с полосами задачи:

 
функция

описывать

Shell_NotifyIcon()

Дисплей и управление иконки близко к области лотка, рядом с часами

SHAppBarMessage()

Отправить сообщение для панели задач системы

 
 
функция файла

Файл является одним из наиболее важных элементов Windows Shell, а графическая среда требует много различных функций, поэтому она нуждается в специальной

Специальная функция обрабатывается. Обратите внимание, что содержимое, показанные в выпуске столбцов таблице ниже, основаны на ближайшем выпуске оболочки.

 
функция

описывать

Версия

FindExecutable()

Возвращает путь к исполняемому файлу зарегистрирован имя указанного файла

Все версии

SHAddToRecentDocs()

Добавьте данный файл в систему «» Latest документ «папка.

Все версии

SHFileOperation()

Используется для копирования, перемещения, удаления или переименования одного или нескольких файлов.

Все версии

SHFreeNameMappings()

Отпустите функцию SHFileOperation () возвращенную в конкретном случае

 
SHGetFileInfo()

Возвращает множество информационных блоков для данного файла

Все версии

SHGetNewLinkInfo()

Установите новое имя ярлыка

4.71

 
Функция папки

Подобно тому, как мы уже говорили, папка является более распространенным, чем в каталоге, который может содержать другие, чем файлы вещей, так что программное обеспечение позади папки

Проблема, которая непосредственно возвращает уникальный идентификатор для каждого элемента в нем. В рабочем столе событий, папка может также иметь свой собственный

Графический набор функций.

функция

описывать

Версия

SHBrowseForFolder()

диалоговое окно для выбора папки Display

Все версии

SHEmptyRecycleBin()

Уничтожить содержимое «корзины»

4.71

SHGetDataFromIDList()

Восстановление данных от счетчика идентификатора

Все версии

SHGetDesktopFolder()

Возвращает указатель IShellFolder для папки «рабочего стола»

Все версии

SHGetDiskFreeSpace()

Возвращает доступное дисковое пространство для указанного диска

4.71

SHGetPathFromIDList()

Возвращает путь к файлу указанного списка идентификаторов (если он присутствует)

Все версии

SHGetSpecialFolder

Location()

Возвращает список идентификаторов специальных системных папок

4.71

SHGetSpecialFolderPath()

Возвращает путь к папке системы специальной (если есть)

Все версии

SHGetSettings()

Возвращает значение папки

4.71

SHInvokePrinterCommand()

Отправить команду на принтер

4.71

SHQueryRecycleBin()

Возвращение «текущее пространство текущего пространства

4.71

 
функция Иконка

Икона является центром графической среды Windows, наиболее важной частью операционной системы оболочки. Поэтому, как правило, считается, что икона

Центр интерфейса программирования оболочки Windows.

функция

описывать

ExtractIcon()

Возвращает иконку исполняемого файла.

ExtractIconEx()

С одной и той же функцией, есть более широкий выбор.

ExtractAssociatedIcon()

На основе класса файла, вернитесь к иконе указанного файла. Handle

 
COM-интерфейс

Мы можем использовать интерфейс COM, как аналогично оболочке, как функции API. Кроме того, использование с CV ++ 6.0

Библиотека MSDN при условии, выполнено в виде ссылки, мы можем разделить COM-интерфейс, участвующий в Shell на четыре категории.

 
Группа

интерфейс

Расширение оболочки

Рекомендуются все COM-интерфейсы всех видов деятельности оболочки, от иконы к соответствующему меню, от активности пользовательского интерфейса для наблюдения файла

расширение пространства имен

COM-интерфейс, включая расширение пространства имен

крюк

Приходите подключить некоторые из интерфейсов, в особенности выполнения программы, преобразования URL и ярлыков сборки Интернета

Разное интерфейс

Некоторые фрагментированы интерфейсы, такие как интерфейс панели пользовательских задач, интерфейс с открытым диалоговым общением, и интерфейс к «моих портфеля» программированиям

 
Для разработчиков, эти интерфейсы не всегда реализуются — в некоторых случаях, вы должны знать их, вы можете правильно

Достаточно использовать их. Здесь более подробно более подробно.

 
интерфейс оболочки

В начале, мы демонстрируем все COM-интерфейсы, а затем использовать их, чтобы сделать небольшую статью на раковине и его расширение.

 
интерфейс

описывать

Версия

IFileViewer,

IFileViewerSite

Позволяют определить файл для данного типа быстро наблюдать модуль в «процессора.

Все версии

IInputObject,

IInputObjectSite

Эти два интерфейса используется для обработки пользовательского интерфейса деятельности и ускорить обработку операций для ускорения SHELL объектов, введенного пользователем.

4.71

IShellIconOverlay,

IShellIconOverlayIdentifier

Используется для отправки файла значка сообщения перекрытия, так что вы можете знать форму перекрытия для данного файла. Значок перекрытия оболочки обращается в значок

Растровое изображение лучше, чтобы лучше подвергать его воздействию, например, ручное перекрытие представляет собой совместное использование этой папки.

4.71

IContextMenu,

IContextMenu2

Позволяет новые связанные пункты меню для специальных типов файлов.

IconTextMenu2 обработки самостоятельной росписи меню

Все версии

IContextMenu3

Так же, как IconTextMenu2, но дает лучший контроль клавиатуры.

4.71

IShellExtInit

Выполните инициализацию расширения оболочки

Все версии

IShellChangeNotify

Функция API SHCHANGENOTIFY () находится на расширение оболочки, в основном, это позволяет написать модуль крюком

Изменение в слое оболочки уведомляется уведомления функции shchangenotify ().

4.71

IExtractIcon

Позволяет получить информацию значок для любой папки.

Все версии

IShellIcon

Обеспечивает другой способ, чтобы получить какую-либо информацию значка файла клип, в конкретном случае, этот метод лучше, чем метод IEXTRACTICON.

Все версии

IShellLink

Разрешить ярлыки для файлов и папок по созданию и решимость файлов

Все версии

IShellPropSheetExt

Используется для добавления страницы свойств в диалоговом окне «Свойства» для указанного класса файла.

Все версии

 
интерфейс Пространство имен

Для того, чтобы написать расширение пространства имен, необходимо знать большое количество COM-интерфейсов. Только некоторые из наиболее важных и некоторые должны быть перечислены здесь.

 
интерфейс

описывать

Версия

IShellView,

IShellView2

Объекты наблюдения используются для определения расширения пространства имен. IshellView2 до сих пор не имеет никаких документов, но он используется в веб-наблюдений.

Все версии

IShellBrowser

Покажите свой браузер, он является детектором или детектор Интернета.

Все версии

IEnumIDList

Обеспечить способ содержания папки перечисления Shell.

Все версии

IShellFolder

Предоставляет метод обработки командной консоли для обработки папки клиента стандартным образом. IShellFolder скрывает код клиента для зонда.

Все версии

IPersistFolder

Сделать инициализации некоторых расширений оболочки и все расширения пространства имен.

Все версии

IPersistFolder2

Кроме того, некоторые из них добавили некоторую поддержку, основанную на наблюдениях Web-приложений.

4.71

IQueryInfo Retrieves flags and infotip text for items in a folder. 4.71

 
Восстановить флаг и информация тега текст пункта папки.

4.71

 
интерфейс Hook

Оболочки Windows дает нам возможность почувствовать определенное количество событий, и позволит нам присоединиться код клиента.

в.

 
интерфейс

описывать

Версия

ICopyHook

Вы можете поразить все файлы в оболочке (копирование, перемещение, удаление, переименование).

Все версии

IURLSearchHook

Позволяет обнаружить детектор пытается преобразовать неизвестный протокол URL.

4.71

INewShortcutHook

Позволяет обнаружить детектор пытается создать новый ярлык Интернета.

4.71

IShellExecuteHook

Вы можете подключить все стартапы из всех новых процессов, экспортируемых ShellExecute () или ShellExecuteEx ().

Все версии

 
Разное интерфейс

Другие интерфейсы в специальной области программирования Shell совместно именуются как разные интерфейсы, такие как: «Мой портфель», общий диалог и

Панель задач и т.д.

 
интерфейс

описывать

Версия

INotifyReplica,

IReconcilableObject,

IReconcileInitiator

Все эти интерфейсы включают в себя процесс настройки файла. В конце концов, обновление версии одного и того же документа производится.

Все версии

ICommDlgBrowser

Специальное поведение просмотра предоставляется, если папка клиента встроен в общем диалоге.

Все версии

ITaskbarList

Разрешить новые кнопки, которые будут добавлены в панели задач системы.

4.71

 
Почему есть API, сочет

Теперь мы уже видели все особенности Windows Shell, она занимает немного времени, чтобы дать функцию API и пикап COM.

Роль рта. По существу, вся функция оболочки может быть разделена на два поле, основные функции и расширения, и проанализирована с этой точки зрения.

Легко отличить от какой области ему принадлежит.

Большая часть большинства функций, предоставляемых вызов API можно рассматривать как «метод» псевдо объект «оболочки». Это псевдо-объект

Позволяет копировать или перемещать файлы или просматривать папки. Вы также можете возобновить информацию о предоставленных документах, и так далее. Первые характеристики объектной модели

Именно с описания себя.

Другими словами, Windows изначально спроектированный чистого C, никогда не рассматривается объектно-ориентированных концепций. следовательно,

Все основные функции не удивлены прямых вызовов API.

COM технология позволяет модулю компонента, а затем использует их, выбрав обнаженный интерфейс. С помощью интерфейса можно легко собрать

Off функции и обеспечивает доступ к данному объекту. Стоя на стенде на стенде, интерфейс COM является упакована вызовом API — вы можете

Это видно в iTastBarlist интерфейса. Это пример компонента интерфейса программирования системы, которая является COM вместо API вызова подвергается часть системы.

Другим примером этого режима является интерфейсом крюка упоминалось выше. Все крючки в Win32 SDK передаём функцию обратного вызова

Число не является программирование COM-интерфейс. Другими словами, оболочка интерфейс программирования содержит крюк, который требует от вас, чтобы написать и зарегистрировать COM-службы должным образом.

Сервер реализован. На самом деле, разница не очень большая, но в системе, они разные.

Существует изменение ветра, дующего с Windows Shell, COM является его источником. В примере уже упоминалось, вы можете увидеть, что

Все COM интерфейсы используются для расширения поведения детектора. Поскольку детектор нужен сервер в процессе проектирования, технологии их параллельно.

, API вызовы и методы интерфейса COM одинаково важны. Их можно рассматривать как две стороны одной монеты (эта монета оболочки), но

Они действительно отличаются.

 
Какие изменения происходят на рабочем столе событий

Обновление активного корпуса настольного приносит некоторые новые функции и оболочка Windows произвела несколько аспектов. это в

Любое возможное место поощряет использование HTML, вводя понятие веб-наблюдения, заказчика настройки, сценариев, а также упростить и эффективный

Иконка модели, а также множество новых функций и COM интерфейсы.

Последний пункт, перечисленные выше, должны обратить особое внимание, например, у нас теперь есть очень оригинальный объект оболочки модель,

С COM, особенность оболочечной в подвергается. Вспоминая это для программистов в головном мозге. До сих пор эта модель

Тип не является совершенным, никакой гибкости вы ожидаете, но это важный первый шаг.

Бросив изменение Shell API не говорит, что события рабочего стола показывает эволюцию значение рабочего стола структуры и папок. особенно:

Объект наблюдения Shell

Структура полосы Задача

Кроме того, есть повышение SHELL объекта наблюдения, так что мы можем выполнять скриптовый код на папке, а также с использованием динамического HTML и сценария

последовательность.

 
Новый объект наблюдения оболочки

Изначально оболочка объекта наблюдения осуществляется и выражается классом shellDll_defview через стек окна. В первой главе вы

Я уже видел:

                                      
Этот скриншот показывает объект наблюдения на рабочем столе, однако, на самом деле то же самое для любой папки. Например, изображение отображается ниже.

Стек окна папки моего компьютера»:

                                      
Подавляющее большинство окно видели здесь работать вместе, чтобы сформировать рамки окна папки (оконной рамы, со списком, панели инструментов и т.д.). Обеспечить дисплей

Класс SHELLD_DEFVIEW онлайнового контента папки (т.е. объекта наблюдения оболочки) наблюдается с его потомками и списками. тем не мение

Подвижный рабочий стол, есть другой объект наблюдения, этот объект также содержит поддержку для HTML и скриптов, называется Web наблюдение, и может быть использован

Папки «наблюдения | Как веб-страница» меню открывает и выключается. Ниже приводится открытое наблюдение, интернет, окна «Мой компьютер»

были свидетелями. Быть

 
Содержание папки отображается в методе шаблона HTML на основе, где наблюдается список, чтобы включить контроль деталей объекта файла.

Соответствующий стек окна:

                            
 
Самая большая разница в том, что следует сразу отметить, что тип окна Internet Explorer_Server, он имеет класс оболочки субокно Встраивание,

Все это образует окно, которое отображает выход через управление WebBrowser, и оболочки встраивание контрольный список пакетов.

Окно списка наблюдения.

WebBrowser представляет собой элемент управления ActiveX, используемый IE3.0 или позже, чтобы показать их содержание: HTML-файл, GIF

И изображения JPEG, а также документы о событиях.

Таким образом, если Web отмечает открыто, то

Папка видна на странице HTML, отображаемой элемент управления WebBrowser.

HTML страница генерируется из шаблона HTML, которые могут быть настроены в случае необходимости.

Список файлов, содержащих файлы встраивается в элементе управления ActiveX и прийти в страницу HTML вместе.

Веб наблюдение также можно открыть папку клиента, однако, в этом случае расширение пространства имен папки пакета необходимо специальное крепление.

Плюс интерфейс.

Что же на рабочем столе, вы можете открыть и закрыть веб-наблюдение через соответствующее меню:

                                      
Когда это наблюдение активности, на рабочем столе объекта наблюдения также использует элемент управления WebBrowser для отображения содержимого на рабочем столе. значок рабочего стола в различных чем фон

Нарисуйте на более высокий уровень, хотя этот «значок слоя» также существует на предыдущем рабочем столе деятельности, веб-наблюдение еще добавлены некоторые HTML «обои»

Вещи, их содержание всегда отображается под значком.

Индивидуальные файлы плюс

Когда Web отмечает открытым, папка вы посещаете использует шаблон HTML. Существует стандартный файл шаблона папки

Folder.htt хранится в веб-подкаталоге Windows, то по умолчанию перед заданием других шаблонов. Если вы хотите узнать его

Исходный код, обратите внимание на, он скрытый файл, поэтому, прежде чем открывать «для отображения всех файлов» настройки, вы не можете видеть это.

Щелкнув правой кнопкой мыши папку, откройте меню, как показано на рисунке:

                                      
 
Выберите «пользовательские папки» … позволяет редактировать мастер редактировать контент непосредственно запустить файл folder.htt. Точнее, вы на самом деле

Редактирование в указанной папке первоначально установленной редактором мастер-шаблона. До тех пор, как вам нужно, может просто редактированием

HTML-файл для изменения внешнего вида папки. Несмотря на то, что это идеальное расширение .htt из HTML-файлов, до тех пор, как вы хотите, вы можете также удалить или набор

Изменение управления списком файлов, отображать только ту информацию, которую вы хотите, чтобы пользователь видел.

Поскольку шаблон папки представляет собой HTML-файл через веб-браузер в IE наблюдаемым, так что вы можете использовать все XML

Особенность, связывание данных, Dynamic HTML, а также возможности создания сценариев, а также изменения в простой папке, чтобы сделать его похожим на приложение. это

Вид настройки очень похож на оригинальное расширение пространства имен.

 
Новая панель задач компоновки

И изменение наблюдаемого объекта, как активная панель задач компоновки рабочего стола также претерпели некоторые изменения. Ниже показана оценка ожидаемого

Читайте и сравнить старую и новую структуру:

                            
 
резюме

В этой главе мы обсудим:

      
Группировка функций API и COM-интерфейсы из функции оболочки Windows

В этой книге главы раскладка

Обзор структуры Shell и ее объектов

С углубленного обсуждения, мы всегда старались сделать очистить структуру интерфейса программирования Shell, отпечатанный на задней части вашего ума, и, таким образом, в следующей главе, пакет

Содержит подробное описание тех наиболее важных функций API. Описание Код используется в основном ++ вызов C SDK функции.

Тогда мы начнем расширять и близко к Shell имен соблюдать некоторые полезные COM интерфейсы, для того, чтобы использовать этот метод

Крюк и его программирование и тестирование начальной объектной модели Shell. Тем не менее имеет долгий путь, до сих пор мы не имеем даже

Там видеть любой код. Они требуют от нас, чтобы провести некоторое время.

 
========

Оболочки Windows Программирование Глава Три

http://blog.csdn.net/chchzh/article/details/2233634

Глава III Действие Файл

Я до сих пор отчетливо помню случай бета-версии появляется Windows95, он распространяется среди друзей и колледжей, так здорово, все

Новый файловый менеджер, все иконки, полноцветный настраиваемый интерфейс, и живой анимированный логотип так, что копирование файлов и удалить площадь

Поверхность операции легче и более интуитивным.

Как истинное программное обеспечение сумасшедшего, мы можем начать конкурс призовой пиццы, он стал первым для того, чтобы иметь возможность перепрограммировать

Люди сделали такое поведение — то есть, как копировать файлы в анимированные моды. Прошло несколько часов времени, чтобы выяснить, в множество новых функций

Функция SHFileOperation (), который представляет собой копию анимации функции отклика по API, он также выполняет функцию всех операций детекторов файлов.

Одно из правил конкурса является создание демонстрационной программы имеет единственную цель этой функции. После этой функции появляется, проблема реальна

По случаю это очень просто. В самом деле, когда я решил использовать эту функцию в программе в качестве стандартной функции для выполнения операций с файлами, вопрос

Появился. Чтобы сделать это, вы должны полностью очистить прототип функция и ее способность на самом деле смешную историю начинаются здесь



В этой главе я собираюсь показать вам SHFileOperation () внутри тайны.

Как правильно использовать логотип и командные функции, поддерживаемые

Как правильно использовать / буфера назначения источника

Что, скорее всего, код возврата

Для вопросов длинных имен файлов, вы можете столкнуться

О File Name Mapping, ранее не возникали проблемы

Как и в любом другом месте этой книги, в этой главе вы найдете некоторые полезные функции, которые вы используете Windows, протолкнуть

Используйте элементы управления, диалоги.

 
SHFileOperation (), что может быть сделано

Чтобы получить ответ на этот вопрос, давайте сначала посмотрим на файл shellapi.h в SHFileOperation () функция

утверждение:

int WINAPI SHFileOperation(LPSHFILEOPSTRUCT lpFileOp);

Кроме того, взять структуру взгляд SHFILEOPSTRUCT, которая представляет собой структуру, определенную в shellapi.h.

typedef struct _SHFILEOPSTRUCT

{

HWND hwnd;

UINT wFunc;

LPCSTR pFrom;

LPCSTR pTo;

FILEOP_FLAGS fFlags;

BOOL fAnyOperationsAborted;

LPVOID hNameMappings;

LPCSTR lpszProgressTitle;

} SHFILEOPSTRUCT, FAR* LPSHFILEOPSTRUCT;

С этой структурой, функция SHFileOperation () может делать все, что вы хотите сделать. Короче говоря, эта функция может быть сделано:

Один или несколько файлов, скопированные из исходного пути к пути назначения

Удаление одного или нескольких файлов, отправить их в Корзину

Переименовать файл

Один или несколько файлов из исходного пути к пути назначения

До сих пор мы ничего не видели нового — по крайней мере, не особо интересные вещи. В самом деле, Win32 API (и библиотека времени выполнения C), имеет

Предоставляя способ сделать то же самое. В частности Win32 API предоставляет CopyFile (), DeleteFile () и MoveFile () для выполнения

Эти задачи.

Тем не менее, появление мощной функции SHFileOperation (), так что вы можете использовать только одну команду, чтобы обрабатывать несколько каталога по умолчанию

Копирование и сборки. Он также «Undo» операции поддерживает, и автоматически переименовывать операции в случае целевого конфликта имен. Наконец, он также является щедрым.

Пустой лист бумаги страницы фильм, который driftes из папки в другую папку.

            
Несомненно, вы можете получить ту же функцию из основных интерфейсов в Win32, но это, возможно, придется сделать много работы.

 
SHFileOperation () функция Как работать

Как и все функции, которые используют только структуру данных в качестве входных параметров, функция SHFileOperation () является достаточно гибкой

Рутина. Это может быть реализовано путем комбинирования различных признаков в соответствующей манере, и использования (или не использование) членов каждой структуры SHFileOpstruct

Многие операции. Давайте посмотрим на роль каждого члена в этой структуре:

 
имя

описывать

Hwnd

Родительское окно ручка всех диалогов, генерируемых с помощью этой функции.

wFunc

Указывает, какая операция должна быть выполнена

pFrom

Источник буфер имя файла

pTo

Буферизация содержащего имя целевого файла (независимо от удаления)

fFlags

Способность влиять на логотип

fAnyOperationsAborted

Содержит значение, возвращаемое значение TRUE или FALSE. Это зависит от отменяет ли пользователь операцию до завершения операции. Определяя этот элемент, вы можете

Это нормально прерываться определения того, что операция является нормальным.

hNameMappings

Данные описывает его на карту объектов имени файла отображение объекта для имени файла структуры SHNAMEMAPPING.

lpszProgressTitle

Строка, используемая для отображения диалогового окна заголовка в той или иной ситуации.

Короче говоря, четыре члена действительно нуждается в дальнейших исследованиях, то они таковы:

WFUNC (косвенно включая PFROM и ВОМ)

fFlags

hNameMappings

lpszProgressTitle

 
Доступные операции

Члены WFUNC указать, что они работают на данный файл, которые предоставляются PFROM и ВЫМ. WFUNC может принимать значение (в

SHELLAPI.H Definition) Да:

Код

ценить

описывать

FO_MOVE

0x0001

Все файлы, указанные в PFROM перемещаются в месте, указанном ВОМ и карданного вала должен быть именем каталога.

FO_COPY

0x0002

Все файлы, указанные в PFROM копируются в место, указанное ВОМ, и их содержание может быть имя каталога или даже PFROM 1: 1

Соответствующий набор файлов.

FO_DELETE

0x0003

Все файлы, указанные в PFROM направляются в «мусорную корзину», и карданный игнорируется.

FO_RENAME

0x0004

Все файлы, указанные в PFROM переименованы имя, указанное в РТО, между PFROM и валом отбора мощности, имя не нужно быть 1: 1.

 
PFROM и ВОМ все буферы, которые содержат один или несколько имен файлов. Если содержать более одного имени файла, вам нужно

Отделить с NULL (символ / 0), а все потребности струнных до конца с двумя нулевыми (/ 0/0) символы, независимо от того, сколько имени файла.

Если PFROM и ВЫЙ не содержат справочную информации (то есть, они не являются полным именем), то функция предполагает, что она должна быть использована

Водитель и каталог, возвращаемый функцией GetCurrentDirectory (). PFROM может содержать групповые символы, или «*. *» Такой характер.

нить.

Установка флага члена FFLAGS структуры SHFileOpstruct может повлиять на все эти операции. Нажмите последовательность символов в онлайн-информации

Из всех знаков. В нашем кратком обсуждении, немного другой способ будет принят, и знак будет помечен в соответствии с фактической рабочей группой,

Если вы хотите таблицу, которая, естественно, расположены, пожалуйста, указывайте Интернет информацию.

 
Обратите внимание на два пустых Эндерс (/ 0/0)

На самом деле, PFROM и ВОМ являются фактом, что указатели на список строки, а не здравым смыслом,

Описание данных не является достаточным. Другими словами, SHFileOperation () всегда ожидает, что будет передаваться двумя символами NULL, даже если вы

Это также верно только одну строку с одним именем файла или с помощью подстановки. Если вы не используете два символа NULL для завершения PFROM и ВОМ

Строка, возможный случай, что функция не выполняется, когда содержание анализируется. На данный момент, она возвращает «не может копирование / перемещение файлов»

Неправильный (код ошибки 1026). Без двух символов NULL, функция может принимать строку символов, байты после одного символа NULL копируется или сдвинут.

Переместить имя файла. Эти байты могут быть все что угодно, не может быть именем файла правовой, так появится ошибка. Поскольку PFROM всегда

Объясните, как список имен файлов, а ВЫЙ только интерпретируются как список имен файлов под флагом FOF_MULTIDESTFILES, поэтому эта ошибка часто

Наряду с PFROM. Во всех других ситуациях, SHFileOperation () предполагает, что ссылки ВЫХ одно имя файла. Таким образом, одним словом NULL

Прекращение достаточно — два терминации NULL требуется только при завершении списка нескольких имен файлов. Множественные цели, если явно не иллюстрирующие

Файл, разрешение на содержание ВОМ останавливается на NULL терминатора.

Метод разбора зависит от того, ссылок указателя списка строк или просто буфер. В целях безопасности, вы всегда должны добавить терминатор.

Как вы планируете присвоить значение строки из PFROM, то же самое, для отбора мощности, если есть несколько файлов назначения, а также. В буквальном, вы можете

С явным плюс один / 0 на конец строки (конечно, строка автоматически прекращается на один символ NULL):

shfo.pFrom = «c://demo//one.txt/0c://demo//two.txt/0»;

Если вы используете переменную, вы можете использовать следующий метод:

pszFrom[lstrlen(pszFrom) + 1] = 0;

 
Перемещение и копирование файлов

Чтобы переместить файл из места в другое, вам необходимо указать:

Содержит буфер имя исходного файла. Это может быть имя последовательности, одно название, в том числе подстановочные

Строки, может быть даже последовательность строка, содержащая жакет.

Каталог назначения. Если переместить список идентифицированных файлов, вы должны подготовить список целевых имен.

Возьмите гарантию ухода 1: 1, что соответствует названию источника. Другими словами, каждое имя исходного файла

Там должно быть имя целевого файла для перемещения или копирования. Если есть несколько целей

Флаг FOF_MULTIDESTFILES должен быть указан в FFLAGS.

Этот логотип может повлиять на работу:

 
Подписать

ценить

описывать

FOF_MULTIDESTFILES

0x0001

Член ВОМ содержит несколько целевых файлов, соответствующих исходному файлу.

FOF_SILENT

0x0004

Операция не требует возврата к пользователю, то есть диалог прогресс бар не отображается, в то время как другие соответствующие окна сообщений по-прежнему отображаются.

FOF_RENAMEONCOLLISION

0x0008

Если целевое местоположение уже содержит файлы переименовывать с файлами, предназначенные или скопированных, этот флаг указывает на то, что целевой файл будет автоматически изменен.

FOF_NOCONFIRMATION

0x0010

Этот флаг делает функцию, чтобы ответить на любой ящик сообщений, только одно исключение, это диалоговое окно для снижения установить каталог по умолчанию

Время для шоу. На этом этапе, требуется флаг FOF_NOCONFIRMMKDIR. (Обратитесь к описанию их позже).

FOF_FILESONLY

0x0080

Этот логотип применяется только к случаю, когда подкаталоги и групповые символы (*. *) Включены. Установите этот логотип, функция обрабатывает только файл без

Введите подкаталог.

FOF_SIMPLEPROGRESS

0x0100

Этот флаг дает упрощенный пользовательский интерфейс: есть окно анимации, но не отображает имя файла, но пас

член LpszProgressTITLE назначенный текст.

FOF_NOCONFIRMMKDIR

0x0200

Если целевой каталог не существует, этот флаг позволяет функции установить каталог по умолчанию. Без этого логотипа, функция предложит установить

Полный путь назначения. Этот логотип немного тонкие отношения со следующим знаком, который будет введен.

FOF_NOERRORUI

0x0400

Если этот флаг установлен, любые ошибки, которые возникают не вызовут окно сообщения на дисплей, все из которых возвращает код ошибки. Этот логотип и предыдущий

Отношения логотип немного тоньше.

FOF_NOCOPYSECURITYATTRIBS  

0x0800

Applicted к WindowsNT, Shell4.71 (WindowsNT имеет IE4.0 и активные рабочие столы) и выше. Этот логотип мешает

Полные файлы свойства копируются.

 
Теперь давайте узнаем больше об этих вариантах более подробно, при перемещении или копировании файлов, есть два основных аспекта: правильно

Landly работать файл, подлежащий передаче и убедитесь, что установленный флаг желателен.

 
Избегайте ненужных диалогов

Если вы хотите работать тихо, вам не нужно, чтобы отобразить сообщение об ошибке диалогового окна или системы, вы можете думать FOF_NOERRORUI

Сочетание FOF_SILENT флагов выбор хороший. Однако, это не так, как я уже говорил, использовать FOF_NoErrori

Просто скрыть окно сообщения неправильно. С другой стороны, FOF_SILENT логотип не мешает этой функции отображать все возможные сообщения

Рамка. На самом деле, FOF_SILENT затрагивает только диалог прогресс бар — то есть, имя файла, который копируется или перемещается в сопровождении обычной

Диалог анимации. Если функция находит данный файл или каталог уже существует в целевом местоположении, он всегда будет отображаться на экране. Чтобы избежать этой линии

Для вас, вам нужно добавить FOF_NOCONFIRMATION к флагу. Это заставит функцию использовать невидимый ДА щелчок на каждом шаге.

поведение. Тем не менее, эта история далека от окончания.

Если целевой путь содержит каталог по умолчанию, все эти флаги являются недействительными. Это до того, как копия или перемещение файла продолжается, это

Функция пытается обеспечить существование целевого каталога, вы, возможно, уже указан каталог, который не существует, то эта функция будет тщательно установлена

Это, однако, первое требует явного признания.

                         
 
Для того, чтобы пропустить этот диалог, необходимо установить флаг FOF_NOCONFIRMMMKDIR. Если этот бит установлен, то функция автоматически устанавливает какое-либо значение по умолчанию.

Каталог не отображает оперативную коробку.

Таким образом, если вы хотите, чтобы завершить копирование (или перемещения) операции без вмешательства пользователя, вы можете использовать следующий логотип

Установите элемент FFLAGS структуры SHFileOpstruct:

FOF_SILENT

FOF_NOCONFIRMATION

FOF_NOERRORUI

FOF_NOCONFIRMMKDIR

Тем не менее, есть еще что-то уточнить, об одновременном использовании FOF_NOERRORUI и FOF_NOCONFIRMMKDIR логотипа.

 
По умолчанию каталог

Интересно, что директория по умолчанию может рассматриваться как ошибка системы, которая появившаяся в диалоге системы. Хотя вы можете установить его

Флаг FOF_NOCONFIRMMKDIR пропускает этот диалог, но FOF_NOERRORUI логотип имеет приоритет над FOF_NOCONFIMMKDIR, эффективно

Диалоговое окно подавлено, что делает флаги участвующих в нем не выбран. Если указаны эти два знака, вы не можете быть предложено авторизоваться

. Каталог, который не существует, и не может автоматически создать каталог Вместо этого эта функция продолжает выполнять так же, как отказ в создании каталога, и вернется:

Код ошибки 117

Отмена Вход FanyOperationsaborted значение ИСТИНА

Не производить мобильные или копировать

Является ли это сказать, что избежать использования FOF_NOERRORUI логотипа? Конечно, если вы хотите абсолютно бесшумно, вы должны неизбежно

Используйте его — чтобы предотвратить все окна сообщений об ошибке не отображалось. Проблема заключается в том, что он также блокирует новый каталог от создаются по умолчанию, и производит ненужный и ненадежный

ошибка. К счастью, есть способ обойти его, то есть, прежде чем использовать этот логотип для вызова SHFileOperation (), убедитесь, что вал отбора мощности

Магазин хранится в существующем полном пути. Win32 предоставляет функцию, которая реализует эту цель:

BOOL MakeSureDirectoryPathExists(LPCSTR DirPath);

Используйте эту функцию, чтобы нужно #include файл imagehlp.h и подключить библиотеку imagehlp.lib.

 
переименовать документ

Функция SHFileOperation () может быть вызвана существующий файл:

                
   
Или аналогично, это вызвано существующим каталогом:

            
   
Настройка FOF_NoconFirmation, функция может быть неявно разрешена заменить старый объект, но появится второй. Вы знаете, если

Если вы выберете файл в детекторе Windows, нажмите кнопку Ctrl-C, затем нажмите клавишу Ctrl-V, и в той же папке появится новый файл.

Этот файл имеет имя файла, похожее на копирование xxxx, который XXXX является выбранным вами файлом. Детектор автоматически переименован в эту новую статью.

Части, чтобы избежать конфликтов. Пока установлен флаг FOF_RENAMEONCOLLIONISE, функция Shfileoperation () также может предоставить эту функцию.

FOF_RENAMEONCOLLISION и FOF_NOCONFirmation флаги объединить диалоговое окно подтверждения, когда замена смещается. Тем не менее, в следующем,

Ваш файл или каталог неизбежно будет перезаписан. Fof_renameoncollision Если вы неразумны

приоритет Вход

 
Отношения между маркерами

До сих пор, должно быть две проблемы в вашем уме, один является то, что отношения между всеми маркерами, с последующим

Какой флаг влияет на какой тип диалога. В следующей таблице дают ответ на вопрос.

 
 
 
Подписать

Диалог ингибирования

Актуальность и приоритет

FOF_MULTIDESTFILES

None

None

FOF_FILESONLY

None

None

FOF_SILENT

Если настройка, диалоговое окно прогресса не отображается.

Дайте приоритет над логотипом FOF_SimpleProgress.

FOF_SIMPLEPROGRESS

None

Ингибирование флага FOF_Silent.

FOF_RENAMEONCOLLISION

Если этот флаг установлен, диалоговое окно замены не отображается, когда файл, который перемещается или скопирован, — это то же имя, что и существующий файл.

Когда имя конфликта, если установлен флаг FOF_NoconFirmation, операция продолжается.

Если оба устанавливаются, это имеет приоритет над FOF_noconfimation. То есть, файл копируется на заданное новое имя вместо перезаписи.

FOF_NOCONFIRMATION

Если настройки, диалоговое окно подтверждения не отображается в любом случае.

Когда имени конфликтуют, охват файла создается, если флаг FOF_RENAMEONCOLLSION не установлен.

FOF_NOCONFIRMMKDIR

Запрос подавления, чтобы создать новую диалог папки

Каталог по умолчанию создает окно сообщения об ошибке в качестве серьезной ошибки.

Диалог подтверждения для установления каталога отображается в виде окна сообщения об ошибке, чтобы зависит от настроек FOF_NoERRORUI.

FOF_NOERRORUI

Подавить все окна сообщений об ошибке.

Дать приоритет над предыдущим флагом. Если настройка, каталог по умолчанию вызывает исключение, которое не обрабатывается и возвращает код ошибки.

 
Рутинная

Для того, чтобы помочь понять характеристики SHFileOperation () функции, приведем простой пример интегрированной программы, которая называется

Шмов. Используйте VC ++ для установления диалогового окна приложения, следующее является пользовательским интерфейсом, который необходимо создать:

        
Вы можете увидеть настройки по умолчанию в функции OnInitDialog (). Эта функция объявлена ​​в Shmove.cpp.

void OnInitDialog(HWND hDlg)

{

// Set the icons (T/F as to Large/Small icon)

SendMessage(hDlg, WM_SETICON, FALSE, reinterpret_cast<LPARAM>(g_hIconSmall));

SendMessage(hDlg, WM_SETICON, TRUE, reinterpret_cast<LPARAM>(g_hIconLarge));

// Initialize the ‘to’ and ‘from’ edit fields

SetDlgItemText(hDlg, IDC_TO, «c://NewDir»);

SetDlgItemText(hDlg, IDC_FROM, «c://demo//*.*»);

// Take care of the ‘progress’ title

SetDlgItemText(hDlg, IDC_PROGRESSTITLE, «This is a string»);

// Select the default operation

CheckRadioButton(hDlg, IDC_COPY, IDC_MOVE, IDC_COPY);

}

 
Чтобы вызвать этот диалог, чтобы вызвать вызов SHFileOperation (), вам необходимо внедрить нажмите кнопку SHFileOperation.

Функция функции onok (). Содержание членов ВОМ и PFROM и связанных с ними логотипов FOF_ устанавливаются в этой функции.

void OnOK(HWND hDlg)

{

SHFILEOPSTRUCT shfo;

WORD wFunc;

TCHAR pszTo[1024] = {0};

TCHAR pszFrom[1024] = {0};

TCHAR pszTitle[MAX_PATH] = {0};

// Установите операцию, которую вы хотите сделать

if(IsDlgButtonChecked(hDlg, IDC_COPY))

wFunc = FO_COPY;

else

wFunc = FO_MOVE;

// получить строку прогресса

GetDlgItemText(hDlg, IDC_PROGRESSTITLE, pszTitle, MAX_PATH);

// получить от получения из буфера

GetDlgItemText(hDlg, IDC_FROM, pszFrom, MAX_PATH);

pszFrom[lstrlen(pszFrom) + 1] = 0;

// добраться до буфера

GetDlgItemText(hDlg, IDC_TO, pszTo, MAX_PATH);

// получить знак

WORD wFlags = 0;

if(IsDlgButtonChecked(hDlg, IDC_FOFSILENT))

wFlags |= FOF_SILENT;

if(IsDlgButtonChecked(hDlg, IDC_FOFNOERRORUI))

wFlags |= FOF_NOERRORUI;

if(IsDlgButtonChecked(hDlg, IDC_FOFNOCONFIRMATION))

wFlags |= FOF_NOCONFIRMATION;

if(IsDlgButtonChecked(hDlg, IDC_FOFNOCONFIRMMKDIR))

wFlags |= FOF_NOCONFIRMMKDIR;

if(IsDlgButtonChecked(hDlg, IDC_FOFSIMPLEPROGRESS))

wFlags |= FOF_SIMPLEPROGRESS;

if(IsDlgButtonChecked(hDlg, IDC_FOFRENAMEONCOLLISION))

wFlags |= FOF_RENAMEONCOLLISION;

if(IsDlgButtonChecked(hDlg, IDC_FOFFILESONLY))

wFlags |= FOF_FILESONLY;

// Позвоните в функцию Shfileoperation ()

ZeroMemory(&shfo, sizeof(SHFILEOPSTRUCT));

shfo.hwnd = hDlg;

shfo.wFunc = wFunc;

shfo.lpszProgressTitle = pszTitle;

shfo.fFlags = static_cast<FILEOP_FLAGS>(wFlags);

shfo.pTo = pszTo;

shfo.pFrom = pszFrom;

int iRC = SHFileOperation(&shfo);

if(shfo.fAnyOperationsAborted)

{

Msg(«Aborted!»);

return;

}

// Результаты операции отображения

SPB_SystemMessage(iRC);

}

Эта функция получает все данные, необходимые им из элементов управления в окне диалога, а затем заполнить в структуре SHFileOpstruct. Если операция теряется

Отказ, фаноперационные члены были заполнены в истине. Есть два незнакомых функция в вышеуказанном коде MSG () и

SPB_SYSTEMMESSAGE (), эти две функции на самом деле упаковка вариант MessageBox (), вы можете написать письмо вариант самостоятельно.

Номер состоит в том, чтобы отслеживать информацию о том, что функция Shfileoperation () фактически возвращается. Теперь мы сосредоточимся на источнике / глобальном буфере, поставьте #include

Resource.h добавляется в Shmove.cpp и устанавливает инженеров.

 
Источник и цель

Существует несколько возможностей при перемещении или копировании файла из источника:

Набор файлов в одну папку

Многие отдельные файлы в отдельные папки

Один файл в одну папку

Многие отдельные файлы с многочисленными одиночными папками

Выше «один файл» означает полный путь к файлу — то есть, файл с полным именем. Соответствующий «групповой файл» является пакет

Эти файлы неизвестны файлы с файлами, идентифицированными подстановочными картами. Только в четвертом случае, упомянутый выше, необходимо использовать

Fof_multiediedestfiles logo.

Выше код получает строку с символами подстановки в PFROM, например: C:. / Декомпрессионной / * В этом случае

Вы должны указать папку назначения. Все, что прошло через ВОМ буфер все названные в папку, если она не содержит inelamic

характер. Таким образом, будет получена ошибка (когда первый файл скопирован или перемещен), как показано ниже.

            
Объяснение вышеизложенного можно управлять путем пропускания два терминации NULL (каждый элемент отделяется одним NULL) для работы несколько файлов, примеры

Например, вы можете написать следующее закодированного в OnOK ():

shfo.pFrom = «c://demo//one.txt/0c://two.txt/0c://three.txt/0»;

shfo.pTo = «c://NewDir»;

Здесь мы упорно работаем, чтобы скопировать / переместить три файла: one.txt, two.txt и three.txt. Все три файла будет скопирован

Бар в корневой C: / в директории NEWDIR. Положение первого исходного файла в C: каталог / Demo, а два других находятся в C: /.

Если PFROM буфер содержит только лишь одно имя, то функция SHFileOperation () имеет два способа обработки содержимого ВОМ.



shfo.pFrom = «c://demo//one.txt/0»;

shfo.pTo = «c://NewDir»;

Если файл или каталог C: / NEWDIR уже существует, то он будет обработан должным образом, то есть файл C: /demo/one.txt или скопировать в каталог

Или заменить существующие файлы. И наоборот, при C: / NEWDIR не существует, то он будет рассматриваться как новое имя файла, и больше не

Имя папки.

Если вы хотите скопировать один файл в новую папку, вы можете рассмотреть возможность добавления обратной косой черты / для работы после того, как содержание ВОМ.

shfo.pFrom = «c://demo//one.txt/0»;

shfo.pTo = «c://NewDir//»;

Странно то, что это приведет к созданию папки по умолчанию. И сделать копию или перемещение файла не удалось. В случае возвращения, он может, как желаемый

Рабочие, поскольку эта папка уже существует во втором выполнении. Так, при копировании отдельных файлов в папку, которая не существует

Что нужно сделать? Единственный способ нормально работать, чтобы добавить символ * в конце имени файла. Это запутанная функция.

Сделать это думать, что это работает выражение подстановочные.

shfo.pFrom = «c://demo//one.txt*/0»;

shfo.pTo = «c://NewDir»;

Другая возможная ситуация такова, что вы хотите скопировать несколько отдельных файлов на такое же количество отдельных файлов. Это должно отвечать двум требованиям, первый

Этот флаг настройки FOF_MULTIDESTFILES, во-вторых, необходимо убедиться, что каждый исходный файл имеет конечный файл — необходимость полного 1: 1

соответствовать. Энный файл в исходном списке файлов копируется или перемещается в п-й файл в списке файлов назначения.

shfo.fFlags |= FOF_MULTIDESTFILES;

shfo.pFrom = «c://one.txt/0c://two.txt/0»;

shfo.pTo = «c://New one.txt/0c://New two.txt/0»;

Если это не выполняется, какой аспект не удалось. Например, следующий код выполняется:

shfo.fFlags |= FOF_MULTIDESTFILES;

shfo.pFrom = «c://one.txt/0c://two.txt/0c://three.txt/0»;

shfo.pTo = «c://New one.txt/0c://New two.txt/0»;

Первый элемент списка целевого файла (т.е. C: / новый one.txt) используются в качестве папки, которая собирается идти, как все исходные файлы. На самом деле, эта операция

Multi-к-одному операции.

Буфер источника может означать файлы и каталоги при использовании шаблонов. Если вы хотите, чтобы функция обрабатывать только файлы, добавьте

Флаг FOF_FILESONLY ОК. Если вы хотите скопировать весь каталог, вам необходимо добавить / а *. * На его пути в конце.

Если не указать флаг FOF_SILENT, функция SHFileOperation () всегда показывает анимацию и прогресс бар.

Окно диалога, в котором метка отображает копирования или перемещения файла. Вы можете скрыть это, установив FOF_SIMPLEPROGRESS логотип

Некоторые метки, которые замещают их с текстом данного в элементе LpszProgressTitle. Это помогает скрыть имя копии или движения.

              
 
Удалить файлы

Удаление файла является простой операцией, которая влияет только на вход буфера PFROM-ВОМ буфер игнорируется. Как спереди,

Детали зависят от настройки логотипа. Соответствующий логотип:

Подписать

ценить

описывать

FOF_SILENT

0x0004

Эта операция не подается обратно пользователю, то есть, не отображается диалоговое окно прогресса. по-прежнему отображается Соответствующее окно сообщения.

FOF_NOCONFIRMATION

0x0010

Этот логотип позволяет функции ответить Да для любого окна сообщения.

FOF_ALLOWUNDO

0x0040

Если установка, этот флаг вынужден переместить файл в удаленный файл в «рецикла станции». В противном случае файл будет физически удален с диска.



FOF_FILESONLY

0x0080

Установите этот флаг заставляет функцию только удалить файл и пропустить элемент каталога. Он применяется только к указанной подстановки.

FOF_SIMPLEPROGRESS

0x0100

Это приводит к упрощению пользовательского интерфейса. Сделайте только один фильм, не сообщая имя удаленного файла. Поколение, чтобы показать, что элемент является LPSZProgressTitle

Места для текста.

FOF_NOERRORUI

0x0400

Если этот флаг установлен, то любая ошибка не может отобразить окно сообщения, но возвращается код ошибки в программе.

 
Логотип, который появляется здесь самое главное, что FOF_ALLOWUNDO, что позволяет программисту решить, является ли файл удаляется один раз, или сохранить его на «возвращение

Закрыть, чтобы восстановить на станции. Если FOF_ALLOWUNDO установлен, то файл будет перемещен в мусорную корзину, и эта операция может быть

UNDO (хотя ручной UNDO). Функция API участвует в «утилизации станции» описывается в главе 10. UNDO функции, доступные только при удалении —

Копирование и нет эквивалентов в движении.

Описание FOF_ALLOWUNDO логотип влияет на пользовательский интерфейс в предыдущей программе. Изменить наш простой проект, чтобы принять удаление

Не очень сложно, в дополнение к запросу. Но ради краткой, мы по-прежнему писать код непосредственно в функцию OnOK ():

ZeroMemory(&shfo, sizeof(SHFILEOPSTRUCT));

shfo.hwnd = hDlg;

shfo.wFunc = FO_DELETE;

shfo.lpszProgressTitle = pszTitle;

shfo.fFlags = FOF_NOERRORUI;

shfo.pFrom = «c://demo//*.*/0»;

Вышеуказанные попытки коды для удаления содержимого всего C: каталог / DEMO и экспорт диалоги:

               
Как видно, «корзина» не упоминаются в окне сообщения, потому что не указано FOF_ALLOWUNDO логотипа. Установленный

FOF_ALLOWUNDO логотип, файл будет изменен в корзину:

               
Другие флаги, перечисленные выше, являются идентичными для копирования или перемещения операции. Таким образом, вы можете установить FOF_SIMPLEPROGRESS или

FOF_SILENT скрывает имя файла, который удаляется, удаляется только файл, установив FOF_FILESONLY. Примечание стандарт FOF_FILESONLY

Не входите в подкаталог. Диалоговое окно, показанное выше не предложено, сколько файлов будут удалены. Тем не менее, это так понятно, потому что

Рассчитанная команда содержит подстановочную (в противном случае будет отображаться количество файлов), так что функция не может получить количество файлов. Это также может быть причиной

Когда файл удаляется, он возвращает причину успеха.

Пресс-конвенция, операционная система будет подтвердить, прежде чем файл будет удален. Если вы обнаружите, что этот диалог не имеет смысла, вы можете

Отвечая на весь запрос Да, вы можете использовать флаг FOF_NOCONFIRMATION. Как правило, один

Операция FO_DELETE показана ниже:

                                      
переименовать документ

Первое, что нужно обратить внимание на этот раздел является то, что вы не можете использовать подстановочные для переименования файла в функции SHFileOperation ().

Измените имя файла, указав одно имя исходного файла в PFROM и одно имя целевого файла для ВОМ, чтобы изменить имя файла:

ZeroMemory(&shfo, sizeof(SHFILEOPSTRUCT));

shfo.wFunc = FO_RENAME;

shfo.pFrom = «c://demo//one.txt/0»;

shfo.pTo = «c://demo//one.xxx»;

Очевидно, что есть две вещи, которые не позволяют делать в операции перераспределения файлов, что явно, то они таковы:

Изменение целевого каталога. Rename просто изменив имя, а не папка.

Покрытые существующий файл

Если вы упорно работать, чтобы выполнить это, вы можете получить только сообщение об ошибке. Возьмите весь код ошибки мы отсоединены следующие параметры пытаются передать

Для функции:

shfo.pFrom = «c://demo//*.*/0»;

shfo.pTo = «c://newdir»;

Очевидно, что это не правильно, и функция возвращает следующее сообщение об ошибке во время:

  
Хотя команда смехотворно возвращается (значение 0), это сообщение достаточно. Однако, это сообщение означает использовать MS-DOS.

Грамматика может нормально работать здесь. Другими словами, мы должны иметь возможность переименовать, например, * .txt в * .xtt. Это в MD-DOS

Нет проблем, при SHFileOperation (), он не может. Если вы испытываете, вы получите следующее сообщение:

                        
Это сообщение вызвано следующими двумя строками кода:

shfo.pFrom = «c://demo//*.txt/0»;

shfo.pTo = «c://demo//*.xtt»;

В данном примере C: каталог / DEMO содержит два файла one.txt и two.txt. Один фактически включен в данном случае

Один из файлов, без расширения. Таким образом, код возврата после этого сообщения 2 «файл не найден».

Так как команда FO_RENAME, кажется, только лишь в одном файле, то флаг влияет на диалог пользователя интерфейс потеряет значение — операции ускорения

Просто сделать пользовательский интерфейс не отображается. Но следующие флаги все еще может чувствовать себя:

Подписать

ценить

описывать

FOF_RENAMEONCOLLISION

0x0008

Если целевое местоположение уже содержит файл с таким же именем, что и файл переименования, этот флаг указывает имя функции.

Чтобы скопировать XXX, то XXX здесь начальное имя файла безымянным. Если этот флаг не установлен, то не будет никакого напоминания, но вы

Сообщение об ошибке будет получено.

FOF_NOERRORUI

0x0400

Если этот флаг установлен, все ошибки, которые происходят не вызывает отображение окна сообщения, но возвращают код ошибки.

 
SHFileOperation () функция возвращает значение

Инлайн информации, SHFileOperation () возвращает 0 в случае успеха, и возвращает не значение 0, когда она выходит из строя. Очевидно, что это верно, но

Не самое полезное объяснение. Повторите эту функцию, вы можете подтвердить, что он имеет много прекращения. На самом деле, мы часто в системе

В неправильно строке запуска в некоторых местах просто возвращает код возврата, полученный из других программ, расположенные ближе к файловой системе.

Отказ Список здесь приведены наиболее распространенные ошибки, возвращаемые SHFileOperation () (может быть, безусловно, не самый подробный).

 
код ошибки

описывать

2

Как уже упоминалось выше, если вы пытаетесь переименовать несколько файлов, появится это сообщение. Описание довольно прямо — система не может быть найдена

Указанный файл — но не понимает, почему он не может найти файл.

7

Когда вы спрашиваете, если вы хотите заменить данный файл, вы ответили на «Отмена», функция возвращает этот код ошибки. Его описание вполне достаточно

Очевидно — Блок управления для хранения разрушается.

115

Эта файловая система неправильно при попытке переименования файла в другую папку. Файл переименования просто изменить имя файла, и не может изменить

папка.

117

IOCTL ошибка (управляющий вход / выход), когда возникает ошибка в пути назначения или когда устанавливается новый каталог, произошла эта ошибка.

123

Вы пытаетесь переименовать файл, однако, имя, которое вы даете, уже существующий файл. Она также имеет бесполезное описание файл

Синтаксис имени, имени каталога или метки тома неправильно.

1026

 
Эта файловая система неправильно при попытке скопировать или переместить файл, который не существует. Как правило, это наводит на восток от источника

Запад должен изменить его. Этот код ошибки приводит к следующему полю ошибок — вы можете подавить его дисплей, установив FOF_NOERRORUI логотипа.

 
Во многих случаях код ошибки возвращается, все из которых связаны с проблемой целевого каталога. Например, если вы его отменили

Попросите просьбой создать каталог, функция возвращает этот код (а не окно сообщения системы). Если есть существенная ошибка в указанном имени каталога,

Появится окно ошибки, вы можете использовать флаг FOF_NoErrori, чтобы подавить его.

 
Два простых процедур о сообщениях об ошибках отображения

Сообщение об ошибке выругался большинство программистов. Поэтому, или написать большое количество кода, кроме текстового описания, или через него

Его способ обхода сообщения об ошибке. Рамки среда обеспечивает некоторые инструменты, такие как MFC, однако, вы не должны хотеть, чтобы разработать такую ​​функцию

Код пересаживают в MFC. Чтобы сделать это, мы генерировали файлы, которые содержат две вспомогательные функции, в приложении А. Первый из них будет пересмотрен

Окно сообщения (). Это расширяет функции за счет увеличения потенциала форматирования общей Е (), переименован в MSG (), код следующим образом:

#include <stdarg.h>

void WINAPI Msg(char* szFormat, …)

{

va_list argptr;

char szBuf[MAX_PATH];

HWND hwndFocus = GetFocus();

// Инициализация функции VA_

va_start(argptr, szFormat);

/ / Формат выходной строки

wvsprintf(szBuf, szFormat, argptr);

// прочитать название дисплея

MessageBox(hwndFocus, szBuf, NULL, MB_ICONEXCLAMATION | MB_OK);

// Отключить функцию VA_

va_end(argptr);

SetFocus(hwndFocus);

}

В основном этот код использует функцию VA_, которая включена в файл stdarg.h заголовка. Список переменных отформатирован с помощью wvsprintf (), в конце концов

Показано с помощью функции нормального MessageBox (). Теперь мы можем написать код, как показано ниже:

iRC = CallFunc(p1, p2);

Msg(«The error code returned is: %d», iRC);

 
Вторая утилита SPB_SYSTEMMESSAGE () (SPB префикс представляет собой оболочку программирования книгу, которая используется, чтобы отличить себя

функция). Он принимает код ошибки и переходит к FormatMessage (), функция API Win32, для всех код ошибки системы (по крайней мере,

Ошибки, определенные в WineError.h) Возвращает функцию, которая описывает текстовую строку. Строка снабжена FormatMessage () собраны вместе, и

Показано вместе:

void WINAPI SPB_SystemMessage(DWORD dwRC)

{

LPVOID lpMsgBuf;

DWORD rc;

rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |

FORMAT_MESSAGE_FROM_SYSTEM |

FORMAT_MESSAGE_IGNORE_INSERTS,

NULL, dwRC,

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, NULL);

Msg(«%s: %ld./n/n/n%s:/n/n%s», «This is the error code», dwRC,

«This is the system’s explanation», (rc == 0 ? «<unknown>» : lpMsgBuf));

LocalFree(lpMsgBuf);

}

 
Работает ли функция правильно?

Несомненно, функция SHFileOperation () имеет некоторые проблемы с его кодом возврата. В частности, даже в входных параметрах

Неправильно, если требуемая операция не может быть завершена, она также возвращает 0 (знак успеха):

                              
Проверьте код, чтобы скопировать или переместить файлы:

shfo.pFrom = «c://demo//one.txt/0»;

shfo.pTo = «c://NewDir»;

Если one.txt файл существует в начальной папке, то операция может быть выполнена нормально. Если нет существования, ошибка 1026 появляется. Не сказать, что это

Желательно. Тем не менее, если вы попробуете следующий код (чтобы убедиться, что файл не соответствует этому режиму), что происходит?

shfo.pFrom = «c://demo//x.*/0»;

shfo.pTo = «c://NewDir»;

Эта функция по-прежнему возвращает 0, даже если нет файла обрабатывается. Такая же ситуация возникает в удаленной файловой операции. Даже если нет файла удаляется

Код возврата по-прежнему успешно. Для целей доверия, это не ошибка или намеренное поведение. Нет недостатков

Является ли операция сертификат достиг желаемого результата, поэтому обязательно помнить, что функция возвращается, чтобы проверить, если файл по-прежнему присутствует.

 
Длинное имя файла

Хотя разработка и внедрение Windows Shell является довести до наибольшего удобства пользователя, однако, некоторые из этих функций для Changwen

Название, кажется, немного проблема. Действительно, это правильно — длинное имя файла. Давайте посмотрим на то, что это длинное имя файла.

Во всех образцах видно выше, указать полное имя целевой папки (обычно с помощью C: / NEWDIR). Данные

Скажем, если полный путь не указан, эта функция предполагает, что текущий каталог, возвращаемый функцией API GetCurrentDirectory ().

Хорошо, теперь проверить это, используйте следующий код в функции SHFileOperation ():

shfo.pFrom = «c://demo//*.*/0»;

shfo.pTo = «NewDir»;

Мы хотим, чтобы скопировать или переместить все файлы в C: каталог / Demo в новый или существующий каталог под названием NEWDIR, который

Расположенный в текущем каталоге. Если имя файла содержится в перенесенном файле не имеет длинное название текста, все операции могут быть выполнены плавно.

Если есть какие-либо длинное имя файла, появится следующий диалог:

                      
Операция, которая происходит в этой функции заключается в попытке сократить длинное имя файла, чтобы убедиться, что он может быть надлежащим образом храниться на целевом диске. Когда целевая машина работает

С Windows3.1, переместите файл в сети, что очень естественно. К сожалению, мы бежим 32-разрядных операционных систем

Копирование и перемещение файлов на одной машине — это система, которая адаптирует для длинных имен файлов. Если имя файла не укорачивается, функция SHFileOperation ()

Не работает.

Удивительно, но если добавить диск к целевой папке, все будет работать. Существует еще неудобно

Ситуация, вы будете удивлены тем, что все операции сглаживания при использовании относительных путей. Странно, что случилось?

Если путь начинается символ является логическим идентификатором доступного диска, функция SHFileOperation () находится в длинном названии текста.

Может работать гладко. В противном случае, он думает, что вы подключаетесь удаленный диск, для этого, поддерживает длинные имена файлов отказ (если не N: диск

Моторы, Подтверждают не удалось). Например, в моей машине, пока е не может работать плавно, это привод CD-ROM.

Это может быть вызвано определенным местом в коде, используемой в рассчитанном файл, и хочет нормально работать, простейший

Одно из способов всегда использовать полное имя.

 
Файл объекта отображения имени

При чтении SHFileOperation (), вы, возможно, уже заметили, осторожный RECK объекта файл отображение имени.

Отказ В частности, этот объект говорил о том, когда Hnamemappings членов структуры SHFileOpstruct.

HNameMappings является указателем на блок памяти — объявлен LPVOID, который содержит определенное количество shNamemapping узлов в блоке памяти.

Состав. Структура данных shNamemapping выглядит следующим образом:

typedef struct _SHNAMEMAPPING

{

LPSTR pszOldPath;

LPSTR pszNewPath;

int cchOldPath;

int cchNewPath;

} SHNAMEMAPPING, FAR* LPSHNAMEMAPPING;

Эта структура идентифицирует файлы, которые копируются, перемещены даже переименовали. Точнее, он не только сохраняет начальное (полный путь) имя файла, но и

Существует также новый (полный путь) имя файла. Таким образом, это предполагает возможность: вы можете получить его во время функции SHFileOperation ().

Полный отчет, что происходит. К сожалению, все не так просто, как воображение.

Во-первых, вы должны сделать член SHFileOperation (), необходимо указать дополнительный знак

FOF_WANTMAPPINGHANDLE. Это не достаточно, чтобы сделать это, потому что только вы также установить флаг FOF_RENAMEONCOLLISION, это

Член заполняется. Кроме того, чтобы сделать заливку функции во всех вещах, а не 0, файловые операции должны быть переименованы, чтобы избежать конфликтов. Все

Это только просто указывает на значения NULL просто hnamemappings.

 
Пример отображения файлов

Создание приложения на основе диалога под названием FileMap для того чтобы испытать что-то о картах файлов. Вот пользователь

интерфейс:

            
Для того, чтобы использовать диалог настройки реального значения, и инициализировать список, вам нужно настроить функцию OnInitDialog (), как это выглядит следующим образом (помните, дополнительные)

#include Resource.h заявление):

void OnInitDialog(HWND hDlg)

{

HWND hwndList = GetDlgItem(hDlg, IDC_LIST);

// наблюдение Установить отчет

LV_COLUMN lvc;

ZeroMemory(&lvc, sizeof(LV_COLUMN));

lvc.mask = LVCF_TEXT | LVCF_WIDTH;

lvc.cx = 200;

lvc.pszText = «Original File»;

ListView_InsertColumn(hwndList, 0, &lvc);

lvc.pszText = «Target File»;

ListView_InsertColumn(hwndList, 1, &lvc);

// Инициализировать области редактирования

SetDlgItemText(hDlg, IDC_FROM, «c://thedir//*.*»);

SetDlgItemText(hDlg, IDC_TO, «c://newdir»);

/ / Установить значок (T / F, как большой / маленький значок)

SendMessage(hDlg, WM_SETICON, FALSE, reinterpret_cast<LPARAM>(g_hIconSmall));

SendMessage(hDlg, WM_SETICON, TRUE, reinterpret_cast<LPARAM>(g_hIconLarge));

}

Теперь Вы можете изменить функцию OnOK (), и дополнительный код показывает, как получить и проверить дескриптор объекта файла отображения имени:

void OnOK(HWND hDlg)

{

TCHAR pszFrom[1024] = {0};

TCHAR pszTo[MAX_PATH] = {0};

GetDlgItemText(hDlg, IDC_FROM, pszFrom, MAX_PATH);

GetDlgItemText(hDlg, IDC_TO, pszTo, MAX_PATH);

SHFILEOPSTRUCT shfo;

ZeroMemory(&shfo, sizeof(SHFILEOPSTRUCT));

shfo.hwnd = hDlg;

shfo.wFunc = FO_COPY;

shfo.pFrom = pszFrom;

shfo.pTo = pszTo;

shfo.fFlags = FOF_NOCONFIRMMKDIR |

FOF_RENAMEONCOLLISION |

FOF_WANTMAPPINGHANDLE;

int iRC = SHFileOperation(&shfo);

if(iRC)

{

SPB_SystemMessage(iRC);

return;

}

// Значение ручки трека

Msg(«hNameMappings is: %x», shfo.hNameMappings);

// Освободить объект в соответствии с рекомендациями

if(shfo.hNameMappings)

SHFreeNameMappings(shfo.hNameMappings);

}

Для того, чтобы обратить особое внимание на последнюю строку коды — релиз имени файла, изображение является простейшими операции, которую можно выполнить на нем. Вы должны позвонить

Shfreenamemapping () и передает параметр Handle принятый от SHFileOperation (). Каждый шаг может быть выполнен, как правило,

И это также может хорошо понять. Может быть, один день, информация Windows может быть так выяснена.

Короче говоря, после выполнения этого кода вы найдете hnamemappings, что всегда нуль, если в результате выполнения (копия, мобильное, переименование) операция

Вызывает конфликт имен. Если происходит операция переименования, эта ручка используется, чтобы сообщить о ситуации, которая на самом деле переименованные файлы, чтобы избежать

Другие документы, отчет дает новое имя и имя исходного файла.

Так что имя файла совпадает с механизмом файлов связи или другим способом, или что-нибудь еще. Это память

Блок позволяет оболочку (и вы), чтобы отслеживать следы файлов, которые переименованы, чтобы избежать конфликтов имен.

Если целевой каталог (этот пример с: / NEWDIR) не существует, или он содержит все имена файлов всех отличные от исходного пути (этот пример

Файл в C: / THEDIR / * Не имеет значения, что указан флаг, Ручка NULL.:

                             
И наоборот, если происходит по крайней мере, один renameful конфликта, это ссылка ручки содержательных блоки данных, поэтому он возвращается.

Адрес памяти.

 
Использовать файл объекта отображения

Получение имени файла отображения объекта Handle только завершает половину работы, теперь давайте оценить, насколько эта ручка полезно!

Только просто в информации (когда ненулевые) hnamemappings указывают на массив shNamemapping структур. Не упомянуто

Размер этого массива получается. Более того, говорит, что это SHFileOperation () не указательный для использования LPVOID дескриптора.

Указатели на массив структур данных. Очевидно, что это не возможно, чтобы просто стать методом велосипедного через группу.

В некоторых старых материалах MSDN вы найдете две упомянутых функций ShgetNameMappingCount () и SHGETNAMAPPINGPTR ()

Отказ Тем не менее, эти две функции теперь не только не объясняет информацию, но и не открывать. Выпуск в Shell32 (от IE4.0 или выше)

Там нет никаких следов в этом в этом. Это не хорошо, потому что они действительно делают функцию вы можете правильно закодировать. Не понимают,

Что удаляет эти функции и поддержку для членов HnameMappings, кажется, родился и старым.

 
Неписаное структура

Информация указана верно, но неполно. Проблема заключается в том, что она игнорирует падение выше

Структура данных между HNameMappings и массивами. Есть два ключа, которые я получаю правильный след, первый, выход из кода ниже



TCHAR* pNM = static_cast<TCHAR*>(shfo.hNameMappings);

Msg(pNM);

Когда я проверить этот код, я выиграл еще один доступ к незаконным, как ни странно, он просто повторил номер ошибки (например, 9). Это

Rename ошибка конфликта? После того, как осмотрел каталог, это действительно. Конечно, я сразу же выполняется еще один чек, используя различные файлы.

Тест и проверить эту идею. Независимо от того, что указывают на то, что hnamemappings, начиная с числа всех отображений имен файлов.

Так что следующий шаг будет Интернет-клиент SDK и MSDN документация, изучить определенные форматы неизвестно разделочной доске, то они таковы:

Окна ShellAPI и операции перетаскивания

MSDN в статье базы знаний Q154123

Эти форматы (один из которых является «отображение имени файла»), при запросе копирования и вставки, или клип из папки в другую

Клип перемещаемого объекта файл используется внутри оболочки. Более интересным является то, много таких форматов в блоке данных в портного плате.

Хранится, в том числе номера и указателя на структуру данных клиента. Числа представляют размер массива, указатель указывает на его первый

элемент.

 
Приближенное решение

Счастлив тот же режим, также может быть применен к объекту отображения, таким образом я определить структуру

Shnamemappingheader имеет следующий формат:

struct SHNAMEMAPPINGHEADER

{

UINT cNumOfMappings;

LPSHNAMEMAPPING lpNM;

};

typedef SHNAMEMAPPINGHEADER* LPSHNAMEMAPPINGHEADER;

Эта структура фактически имеет тот же формат, что и данные указаны по HNameMappings. Чертеж показывает, что это также показывает доступ

SHNAMEMAPPING структуры данных:

                        
Таким образом, написать функцию, чтобы перечислить все объекты отображения имен файлов непосредственно, когда это, я называю это.

Shenumfilemapping (). Перед самой функции наблюдения, первый расширить предыдущий OnOK (), чтобы включить вызовы функции:

void OnOK(HWND hDlg)

{



// Отслеживание этого значения Handle

Msg(«hNameMappings is: %x», shfo.hNameMappings);

// объект сопоставления файлов Перечислите

SHEnumFileMapping(shfo.hNameMappings, ProcessNM,

reinterpret_cast<DWORD>(GetDlgItem(hDlg, IDC_LIST)));

// Освободить объект в соответствии с рекомендациями

if(shfo.hNameMappings)

SHFreeNameMappings(shfo.hNameMappings);

}

Функция ShenumFilemapping () принимает ручку, процесс обратного вызова, и общий буфер. Он перечисляет все shNamemapping и пройти по одному

Отправляйте их в функцию обратного вызова, чтобы сделать дальнейшую обработку.

int WINAPI SHEnumFileMapping(HANDLE hNameMappings, ENUMFILEMAPPROC lpfnEnum,

DWORD dwData)

{

SHNAMEMAPPING shNM;

// Проверка ручки

if(!hNameMappings)

return -1;

// Получить структурную голову

LPSHNAMEMAPPINGHEADER lpNMH = static_cast<LPSHNAMEMAPPINGHEADER>(hNameMappings);

int iNumOfNM = lpNMH->cNumOfMappings;

/ / Проверьте указатель функции, если нуль, возврат к количеству изображений непосредственно

if(!lpfnEnum)

return iNumOfNM;

// Перечислите объект

LPSHNAMEMAPPING lp = lpNMH->lpNM;

int i = 0;

while(i < iNumOfNM)

{

CopyMemory(&shNM, &lp[i++], sizeof(SHNAMEMAPPING)); if(!lpfnEnum(&shNM,

dwData))

break;

}

/ / Возвращает число объектов, которые на самом деле обрабатывать

return i;

}

Функция SHenumFilemapping () такая же, как модель, после большинства функций перечисления Windows. Он принимает функцию обратного вызова и универсальный буфер

Эта буферизация используется для сохранения вызывающей программы для передачи клиентских данных функции обратного вызова. Кроме того, он ожидает, что функция обратного вызова возвращает 0, когда перечисление заканчивается.

Мой определенный тип функции обратного вызова EnumfilemApproc:

typedef BOOL (CALLBACK *ENUMFILEMAPPROC)(LPSHNAMEMAPPING, DWORD);

Эта функция принимает указатель на объект shNamemapping и клиентских данных, посылаемых вызова.

Конечно, использование класса перечислите функции перечисления всех структур является личным предпочтением. Эквивалент также может использовать интерфейс навигации для обеспечения

FindfirstShnameMapping () и findnextshnamemapping (функции).

На самом деле, это гораздо лучше, чтобы выполнить эту операцию с помощью функции обратного вызова. Здесь принимается от любого из него, что я использую (ProcessNM ())

Значения полей PszoldPath и PSZNewPath извлекаются в структуре shNamemapping. И список отчетов добавляется в отчете:

BOOL CALLBACK ProcessNM(LPSHNAMEMAPPING pshNM, DWORD dwData)

{

TCHAR szBuf[1024] = {0};

TCHAR szOldPath[MAX_PATH] = {0};

TCHAR szNewPath[MAX_PATH] = {0};

OSVERSIONINFO os;

// Какой ОС мы должны знать?

os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

GetVersionEx(&os);

BOOL bIsNT = (os.dwPlatformId == VER_PLATFORM_WIN32_NT);

// В NT, структура shNamemapping содержит строку Unicode

if(bIsNT)

{

WideCharToMultiByte(CP_ACP, 0, reinterpret_cast<LPWSTR>(pshNM->pszOldPath),

MAX_PATH, szOldPath, MAX_PATH, NULL, NULL);

WideCharToMultiByte(CP_ACP, 0, reinterpret_cast<LPWSTR>(pshNM->pszNewPath),

MAX_PATH, szNewPath, MAX_PATH, NULL, NULL);

}else{

lstrcpy(szOldPath, pshNM->pszOldPath);

lstrcpy(szNewPath, pshNM->pszNewPath);

}

// Сохранить список наблюдения Handle

HWND hwndListView = reinterpret_cast<HWND>(dwData);

// Установить / 0 отдельные строки

LPTSTR psz = szBuf;

lstrcpyn(psz, szOldPath, pshNM->cchOldPath + 1);

lstrcat(psz, __TEXT(«/0»));

psz += lstrlen(psz) + 1;

lstrcpyn(psz, szNewPath, pshNM->cchNewPath + 1);

lstrcat(psz, __TEXT(«/0»));

/ / Stroke для наблюдения отчета

LV_ITEM lvi;

ZeroMemory(&lvi, sizeof(LV_ITEM));

lvi.mask = LVIF_TEXT;

lvi.pszText = szBuf;

lvi.cchTextMax = lstrlen(szBuf);

lvi.iItem = 0;

ListView_InsertItem(hwndListView, &lvi);

psz = szBuf + lstrlen(szBuf) + 1;

ListView_SetItemText(hwndListView, 0, 1, psz);

return TRUE;

}

Обратите внимание, что в Windows NT, строка в структуре shNamemapping это формат Unicode. Таким образом, если операционная система NT, включите

Изменение строк в формате ANSI, чтобы использовать их в подпрограммах. Также отмечу, что DWDATA буфер используется для передачи списка Дескриптора

Перезвоните.

После интегрирования этого кода с предыдущим примером, теперь вы можете дать вызывающее SHFileOperation функции ()

Подробный процесс реновации файла. В типичном случае, вы можете увидеть следующую ситуацию:

             
резюме

В этой главе обсуждается функция SHFileOperation (), который был тщательно протестирован каждый аспект. Из

Копирование, перемещение, переименовывать или удалять файлы, и установить флаг, чтобы изменить поведение функции, а затем расширить возврат к некоторой неписаной информации

Обсуждение на кодирования, ОШИБКИ, функциональных дефектов. Таким образом, в этой главе, дать ему:

Как программировать SHFileOperation ()

Наиболее распространенное программирование является неправильным.

Эта функция нехватка информации

Как использовать отображение имен файлов

========

Написать простое расширение оболочки Windows

http://blog.csdn.net/clever101/article/details/7583460

 
один. программа для написания SHELL

Среда разработки здесь используется WindowsXP + SP3, VS 2005 + SP1 (должна поддерживать VS версии выше VS 2005, VC

6,0 Оценка не поддерживается).

1 Создайте новый проект ATL, введите название проекта: ImportShell, в частности, как:

2. Выберите: Dynamic Link Library (DLL) в настройках приложения: Dynamic Link Library (DLL), другие параметры используются настройки по умолчанию, конкретное изображение будет показано ниже:

Это создаст ATL проект после нажатия кнопки.

3 Новый объект ATL простого (английский вариантом VS является atlsimple объекта), конкретным образом:

4 Введите направление: Importshellext, другой VS поможет вам заполнить, конкретное изображение:

Новые классы CIMPORTSHELLEXT требуют нового наследования двух базовых классов: IShellExtInit и IContextMenu. Новая функция интерфейса в основном

Четыре:

Когда наше расширение оболочки загружено, проводник будет вызывать функцию QueryInterface () СОМ объекта, который мы реализовали.

Указатель ISHELLEXTIT интерфейс.

Этот интерфейс имеет только один метод Initialize (), его прототип функции:

HRESULTIShellExtInit::Initialize ( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj,HKEY 

hProgID ); 

Проводник использует этот метод для передачи всей информации.

PIDLFolder переменная PIDL папки, в которой пользователь выбирает файл находится. (A PIDL [Указатель на список ID] Да

Структура данных, который однозначно идентифицирует любой объект в пространстве имен оболочки, объект в пространстве имен оболочки может быть

Объекты в реальной файловой системе.)

pDataObj указатель интерфейса IDataObject, через который мы можем получить выбранную операцию пользователя от имени файла.

HProgid является ключевой переменной HKEY реестра, который может быть использован, чтобы получить регистрационные данные нашей DLL.

После того, как проводник инициализирует расширения, оно будет затем вызвать метод IContextMenu, чтобы добавить пункты меню, Упоминание

Подсказка в строке состояния и реагировать на выбор пользователя выполнения.

Добавить прототип функции IContextMenu метода,: общественность:

[cpp] view plain copy

// IContextMenu  

STDMETHOD(GetCommandString)(UINT, UINT, UINT*, LPSTR, UINT);  

STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO);   

STDMETHOD(QueryContextMenu)(HMENU, UINT, UINT, UINT, UINT);    

Изменение контекстного меню IContextMenu имеет три метода.

Первый QueryContextMenu (), который позволяет изменять контекстное меню прототип.:

[cpp] view plain copy

HRESULT IContextMenu::QueryContextMenu ( HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, 

UINT uidLastCmd, UINT uFlags );   

HMENU контекстного меню ручка.

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

UidFirstCMD и UidlastCMD является диапазоном значений команды ID меню можно использовать.

Uflags идентифицирует причину вызова проводника QueryContextMenu ().

Возвращаемое значение отличается в зависимости от документа, который вы ищете.

Книга Дино Эспозито говорит, что возвращаемое значение является числом пунктов меню, которые Вы добавляете.

MSDN с VC6.0 также сказал, что команда ID последнего пункта меню мы добавили добавить 1.

И последние MSDN сказали:

Установить возвращаемое значение разности максимальной командного ID, присвоенный каждый пункт меню, плюс 1.

Например, предположим, что IdcmdFirst установлен на 5, и добавить три пункта меню, команда ИД 5, 7 и 8, соответственно.

В это время, возвращаемое значение должно быть: MAKE_HRESULT (severity_success, 0, 8 — 5 + 1).

Я было сделано Дино объяснить, и у меня есть хорошая работа.

На самом деле, его метод согласуется с последним MSDN, до тех пор, пока вы используете uidfirstcmd в качестве первого меню ID,

Подключение ID пункта меню плюс 1 каждый раз.

Мы временно разворачивать только пункт меню, так QueryContextMenu () очень просто:

[cpp]

HRESULT CImportShellExt::QueryContextMenu( HMENU hmenu,UINT uMenuIndex, UINT uidFirstCmd, 

UINT uidLastCmd, UINT uFlags )  

{  

// Если логотип содержит CMF_DEFAULTONLY, мы не делаем ничего.

    if ( uFlags & CMF_DEFAULTONLY )   

    {   

        return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );   

    }   

  
InsertMenu (HMENU, UmenuIndex, MF_BYPOSITION, UIDFIRSTCMD, _T ( «МАШИНОСТРОЕНИЕ»));

    return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 1 );  

}  

Сначала мы проверяем UFLAGS.

Вы можете найти все интерпретации всех флагов в MSDN, но для расширения контекстного меню, только одно значение имеет важное значение:

CMF_DEFAULTONLY.

Этот флаг указует оболочки расширения пространства имен для резервирования пункта меню по умолчанию. В это время нашего расширение оболочки не должно вступать в любом пользовательском меню.

Пункт, почему это причина, почему мы должны возвращать 0.

Если флаг не установлен, мы можем изменить в меню (с помощью ручки HMENU) и возвращает 1 Скажите скорлупу. Мы добавили.

Пункт меню.

Следующий метод IContextMenu называть это GetCommandString (). Если пользователь правой кнопкой мыши в окне браузера

Текстовый файл, или выберите текстовый файл, в меню Файл, в строке состояния отображается подсказка справки.

Наша функция GetCommandString () возвращает справку строку для отображения браузера.

Прототип GetCommandString () является:

[cpp] view plain copy

HRESULT IContextMenu::GetCommandString ( UINT idCmd, UINT uFlags, UINT *pwReserved, LPSTR 

pszName, UINT cchMax );  

IDCMD счетчик на основе счетчик, определяет, какой пункт меню выбран.

Потому что у нас есть только пункт меню, IDCMD всегда равен 0. Но если мы добавим 3 пунктов меню, IDCMD может быть 0, 1 или 2.

Uflags другой набор маркеров (я расскажу позже).

PWRESERVED можно пренебречь.

Pszname указывает на буфер, принадлежащий оболочке, мы скопируем справочную строку в буфер.

CCHMAX является размером буфера.

Возвращаемое значение S_OK или E_FAIL.

GetCommandString () также может быть вызван, чтобы получить действие пункта меню ( «Глагол»).

Глагол является независимым от языка строка, которая идентифицирует образ, который может быть добавлен к объекту файла.

Существует подробное описание в документации ShellExecute (), а содержание глагола достаточно, чтобы написать статью, простое объяснение: Глагол

В строке непосредственно в реестре (например, «Открыть» и «Печать» и другие строки также может быть создано с помощью контекстного меню. Это будет проходить

Вызов ShellExecute () Выполнить код, который реализует код в расширении оболочки.

В любом случае, я сказал, что это просто объяснить роль получения GetCommandString ().

Если проводник требует строки помощи, мы предлагаем его. Если проводник требует Глагола, мы его игнорируем.

Это роль параметров uflags.

Если uflags устанавливает бит GCS_HELPText, Проводник в запросе строки справки. И если GCS_Unicode это набор

Установить, мы должны возвращать строку Unicode.

Наш GetCommandString () выглядит следующим образом:

[cpp] view plain copy

#include <atlconv.h>  

/ / Чтобы преобразовать макросы, используя строку ATL

               
HRESULT CImportShellExt::GetCommandString( UINT idCmd, UINT uFlags,UINT* pwReserved, LPSTR 

pszName, UINT cchMax )   

{  

    USES_CONVERSION;   

// Проверка IDCMD, оно должно быть, потому что у нас есть только один пункт меню.

    if ( 0 != idCmd )   

       return E_INVALIDARG;   

  
// Если проводник требует строки помощи, скопируйте его в буфер при условии.

    if ( uFlags & GCS_HELPTEXT )   

    {  

LPCTSTSTSZTEXT = _t ( «Число файлов в статистической папке»);

        if ( uFlags & GCS_UNICODE )  

        {   

/ / Мы должны преобразовать PSZName в строку Unicode, следовать Unicode копирования строки API.

            lstrcpynW ( (LPWSTR) pszName, T2CW(szText), cchMax );   

        }   

        else  

        {   

// Использование строки ANSI скопировать API, чтобы вернуться в строку справки.

            lstrcpynA ( pszName, T2CA(szText), cchMax );   

        }   

        return S_OK;  

    }   

    return E_INVALIDARG;   

}  

Существует ничего особенного здесь код, я использую жестко строку и преобразовать его в соответствующий набор символов.

Если вы никогда не использовать строку ATL для преобразования макросов, вы должны научиться, потому что, когда вы передаете строку Unicode к COM и OLE функций

А использование преобразования макросов очень полезно.

Я использую T2CW и T2CA в коде для преобразования строк TCHAR в Unicode и ANSI строки, соответственно.

Uses_Conversion Macro в начале функции фактически объявляет локальную переменную, которая будет преобразована в макрос.

Один вопрос, следует отметить: lstrcpyn () гарантирует, что целевая строка будет заканчиваться нулем.

Это отличается от C перспективы (CRT) функция strncpy (). Когда длина исходной строки должны быть скопировано больше или равна cchmax, strncpy () не является

Концевой значение NULL, будет добавлен.

Я рекомендую использовать lstrcpyn (), так что вы не должны вступать в проверку, чтобы убедиться, что строка завершается нулем после каждого strncpy ().

Код.

Последний способ интерфейса IContextMenu является InvokeCommand (). Этот метод будет скорректирован, когда пользователь нажимает на пункт меню мы добавляем.

Используйте его прототип функции.:

[cpp] view plain copy

HRESULT IContextMenu::InvokeCommand ( LPCMINVOKECOMMANDINFO pCmdInfo );  

Структура CMinvokeCommandInfo имеет много информации, но мы заботимся только о двух членах LPVERB и HWND.

Есть две функций параметра LPVERB — это OrS имени ГЛАГОЛА (действия), или значения индекса пункта меню щелкнутого.

HWND является дескриптором окна браузера, в котором пользователь активирует наше расширение меню.

Потому что у нас есть только пункт меню расширения, нам нужно только проверить параметр lpverb, если 0, то мы можем определить нас

Пункт меню нажата. Самый простой код, который я могу думать, чтобы выскочить сообщение, и коды здесь сделали так много. Информация

Поле отображается имя выбранной папки. Конкретный код выглядит следующим образом:

[cpp] view plain copy

HRESULT CImportShellExt::InvokeCommand( LPCMINVOKECOMMANDINFO pCmdInfo )  

{  

    // If lpVerb really points to a string, ignore this function call and bail out.  

    if ( 0 != HIWORD( pCmdInfo->lpVerb ) )  

        return E_INVALIDARG;  

  
    // Get the command index — the only valid one is 0.  

    switch ( LOWORD( pCmdInfo->lpVerb) )  

    {  

    case 0:  

        {  

            TCHAR szMsg [MAX_PATH + 32];  

WSPrintf (SZMSG, _T ( «выбрана папка% s»), m_szfile;

MessageBox (pcmdinfo-> HWND, szmsg, _t ( «информация»),

                MB_ICONINFORMATION );  

            return S_OK;  

        }  

        break;  

    default:  

        return E_INVALIDARG;  

        break;  

    }  

}   

В это время, вы можете спросить: Как операционная система знает, что мы должны вставить это меню? Здесь регистрация COM-компонента участвует.

вопрос. Так называемая регистрация COM-компоненты, просто записывает соответствующую информацию о COM-компоненте в реестр, то операционная система переходит в системном реестре путем чтения

Информация, связанная с нагрузкой COM компонентов. программа регистрации SHELL делится на два этапа:

Первый шаг в WIN NT / WIN 2000 гарантирует, что ваше расширение оболочки может быть вызвано без привилегий администратора, вам необходимо зарегистрироваться

Таблица HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / Windows / CurrentVersion / Shellextensions / AppROFED Добавить

Наша информационная программа. Это необходимо DLLRegisterServer функции (регистрация функция) и Dllunregister сервер письмо, необходимое

Количество (обратная функция регистрации). Кодовое шоу, как показано ниже:

[cpp] view plain copy

// DLLRegisterServer — Добавление элементов в системном реестре

STDAPI DllRegisterServer(void)  

{  

// Регистрируют все интерфейсы объекта, типа библиотеку и библиотеки типов

    if ( 0 == (GetVersion() & 0x80000000UL) )  

    {  

        CRegKey reg;  

        LONG    lRet;  

  
        lRet = reg.Open ( HKEY_LOCAL_MACHINE,  

            _T(«Software//Microsoft//Windows//CurrentVersion//Shell Extensions//Approved»), 

 
            KEY_SET_VALUE );  

  
        if ( ERROR_SUCCESS != lRet )  

            return E_ACCESSDENIED;  

  
        lRet = reg.SetValue ( _T(«ImportShell extension»),   

            _T(«{06001B8E-8858-4CEE-8E91-60E12A6C81A7}») );  

  
        if ( ERROR_SUCCESS != lRet )  

            return E_ACCESSDENIED;  

    }  

  
    HRESULT hr = _AtlModule.DllRegisterServer();  

    return hr;  

}  

  
  
// DllUnregisterServer — Удалить элемент из системного реестра

STDAPI DllUnregisterServer(void)  

{  

    if ( 0 == (GetVersion() & 0x80000000UL) )  

    {  

        CRegKey reg;  

        LONG    lRet;  

  
        lRet = reg.Open ( HKEY_LOCAL_MACHINE,  

            _T(«Software//Microsoft//Windows//CurrentVersion//Shell Extensions//Approved»), 

 
            KEY_SET_VALUE );  

  
        if ( ERROR_SUCCESS == lRet )  

        {  

            lRet = reg.DeleteValue ( _T(«{06001B8E-8858-4CEE-8E91-60E12A6C81A7}») );  

        }  

    }  

  
    HRESULT hr = _AtlModule.DllUnregisterServer();  

    return hr;  

}  

Одна из проблем здесь reg.setValue (_t ( «расширение importshell),

           _T(«{06001B8E-8858-4CEE-8E91-60E12A6C81A7}») );

Как это имя ключа и значение середины. В самом деле, когда вы создаете новый объект COM простой, вы автоматически генерировать текст importshellext.rgs.

Части, откройте этот файл importshellext.rgs, будет следующий файл:

    ImportShell.ImportShellExt.1 = s ‘ImportShellExt Class’

    {

       CLSID = s ‘{06001B8E-8858-4CEE-8E91-60E12A6C81A7}’

    }

    ImportShell.ImportShellExt = s ‘ImportShellExt Class’

    {

       CLSID = s ‘{06001B8E-8858-4CEE-8E91-60E12A6C81A7}’

       CurVer = s ‘ImportShell.ImportShellExt.1’

    }   

Это имя ключа, как правило, берутся из удлиненого названия программы, такие как расширение importshell, ключевое значение из его GUID формы строки

: {06001B8E-8858-4CEE-8E91-60E12A6C81A7}。

 

Второй этап включает в себя тип файлов, управляемых с помощью программы оболочки. Например, мы просим, ​​чтобы выбрать папку всплывала это правую кнопку мыши.

меню. В это время, вам нужно добавить некоторую информацию о файле importshellext.rgs:

    NoRemove Folder

    {

       NoRemove ShellEx

       {

           NoRemove ContextMenuHandlers

           {

              ForceRemove ImportShellExt = s'{06001B8E-8858-4CEE-8E91-60E12A6C81A7}’

           }

       }

    }

 

Это на самом деле очень хорошо понимают: Каждая строка представляет собой раздел реестра, «HKCR» является аббревиатурой HKEY_CLASSES_ROOT.

Noremove Ключевое слово указывает на то, что ключ не должен быть удален при выхода из системы СОМ-сервер.

Последняя строка немного сложнее. Forceremove ключевое слово указывает на то, если ключ уже существует, то кнопка должна быть удалена перед добавлением новой кнопкой.

Остальная часть этой строки сценария определяет строку, которая будет сохранена в качестве значения по умолчанию ключа importshell.

 

Если вы хотите работать в текстовый файл, вы можете добавить эту информацию:

NoRemove .txt

    {

       NoRemove ShellEx

       {

           NoRemove ContextMenuHandlers

           {

              ForceRemove ImportShellExt = s'{06001B8E-8858-4CEE-8E91-60E12A6C81A7}’

           }

       }

    }

 

Если вы хотите работать с любым типом файла, это:

NoRemove *

    {

       NoRemove ShellEx

       {

           NoRemove ContextMenuHandlers

           {

              ForceRemove ImportShellExt = s'{06001B8E-8858-4CEE-8E91-60E12A6C81A7}’

           }

       }

    }

 

 

два. отладка программы Shell

 

На WIN NT / 2000, вы можете найти следующее:

HKCU/Software/Microsoft/Windows/CurrentVersion/Explorer

И создать значение типа DWORD под названием DesktopProcess 1. Это сделает рабочий стол и панель задач в том же самом процессе, в то время как всякий

Окно работает Проводник в каждом из своих собственных процессов. То есть, вы можете отлаживать в одном окне обозревателя.

До тех пор, как вы закроете окно, ваша DLL будет удален немедленно, что позволяет избежать обновления, потому что DLL который используется Windows, и не может быть заменен.

И если это произойдет, вы должны выйти после входа в систему, а затем войти в Windows, чтобы заставить удалить распространение оболочки.

DLL. Быть

      

Нажмите клавишу F5, диалоговое окно появится, а затем введите путь Exploer.exe, как показано ниже:

В это время, предупреждающее окно, как правило, появляются, и не спросил, как показано ниже:

        

Затем откройте окно моего документа, как показано ниже:

В это время, вы можете установить точку останова для отладки в вашем коде.

 

три. Развертывание программы оболочки

Развертывание оболочки программы проста, только два новых пакетных файлов под сгенерированного каталога DLL:

Install.bat — Сценарий установки программы SHELL является:

regsvr32.exe ImportShell.dll

Uninstall.bat — деинсталлятор программы SHELL:

regsvr32.exe /u ImportShell.dll

 

Вы можете установить или удалить программу оболочки в управлении этих двух пакетных файлов.

Четыре. проблемы Знакомства и решения

Linkr ошибка инструмент LINK: Fatal lnk1168 Ошибка: не удается открыть ../ OUTDIR / отладки

/ImportShell.dll for writing。

 

Эта проблема возникает при изменении GUID объекта регистрации COM. Решение состоит в том, чтобы открыть диспетчер задач и убить все Explorer.exe.

Затем создайте новый процесс Explorer.

использованная литература:

«Shell Extension для Windows Программирование Полное руководство», Автор: Майкл Данн.

 

Исходный код адрес загрузки: CSDN скачать.

========

Оболочки Windows Глава 7 Программирование

Глава 7 инвазивный Shell

Как и все другие процессы WIN32, оболочка также имеет свой собственный адресное пространство памяти, которое совершенно неизвестна в других приложениях.

Доступ пространство. Для того, чтобы войти в этом адресном пространстве, мы должны пройти определенное количество контрольных точек, так же, как мы пересекаем границу страны.

Что мы заинтересованы в Windows Shell? Является ли это Эдем? Является ли он богат золотой рудник? Это рай

У вас есть сокровище? К сожалению, это не так. Введите оболочку, просто позволяют нам коду записи для выполнения операций, которые не могут быть выполнены вне оболочки

делать. При инъекции в адресное пространство кода в процессе Win32, мы можем контролировать поведение этой программы, можно фильтровать, проверка

Посмотрите на поток сообщений, и заставить его делать (или не делать) определенную операцию.

Для того, чтобы достичь этого, мы можем сделать несколько различных способов. Мощные способы, чтобы использовать определенные возможности для Windows (или

Слабость) Введите в адресное пространство процесса и subcatenification его. Кроме того, некоторые процедуры четко позволяют внешние модули вмешательства, и они могут работать вместе.

делать. На данный момент мы должны сделать, это написать модуль с необходимым интерфейсом (обычно сервер в пределах процесса COM) и требуются в основном модуле.

Регистрация на месте.

Третий способ, чтобы каждый процесс работает в своем собственном пространстве, но построить канал, чтобы они могли общаться. Вы можете думать

Как программа достаточно влияет на другую строку программы — или, программа может сделать некоторые операции, которые делают другую программу

Отказ В этом случае существует связь потенциального канала для этих модулей — позволяет детектор знать, что вы можете сделать, чтобы файл или папку.

Таким образом, используется таким образом.

В этой главе мы приведем примеры этих трех модулей. Также пояснил:

Как ощутить изменения в системе документооборота

Как ваше событие уведомит Shell

Как ввести в адресное пространство оболочки

В результате, как изменить поведение кнопки «Пуск» из

Мы ориентируемся на две части программного обеспечения Win32: крюками и объектов уведомления. Эти механизмы скрыты во многих из ключевых моментов, мы будем изучать.

Отказ

 
событие уведомления Shell

Вы, наверное, заметили, что зонд может ощущать какие-либо изменения в системе документов очень быстро, и периодически обновляется текущее наблюдение и

Любые изменения, вызванные другими приложениями. Например, когда вы открываете окно DOS и окно зонда, выберите один и тот же каталог, в обоих, то

Создание каталога в окне DOS, последняя не будет иметь дисплей обновления гистерезиса.

Кажется, что-то говорит детектор, который установил новую папку. При этом жилье, все это возможно

Управления является объектом уведомления.

 
объект уведомления

Объект уведомления является основным объектом синхронного потока. Концепция является то, что вы создаете такой объект и дать ему немного, чтобы настроить такие вещи.

Свойства части затем блокировать наступление события нити ожидания. Если вы хотите, вы можете рассматривать объект уведомления в качестве специального события, в

Он чувствует, что файловая система автоматически изменяет. При уведомлении объекта, вы можете управлять каталогами, subtails, и даже весь диск,

А файлы и папки события мониторинга — установить, переименование, удаление, изменение атрибутов и т.д.

 
Использование объекта Notification

Win32 SDK определяет функцию объектов уведомления три операции, то они таковы:

FindFirstChangeNotification()

FindNextChangeNotification()

FindCloseChangeNotification()

Первая функция «устанавливает» новый объект уведомления, и последняя функция удаляет этот объект. Удивительно, но вы не должны относиться другие основные объекты.

Использование CloseHandle (), чтобы освободить объект уведомления.

Как уже упоминалось ранее, за объектом уведомления является стандартным Win32 объект синхронизации, но она добавила мониторинга файловой системы.

Особое поведение. За FindFirstChangeNotification () и FindNextChangeNotification () функция захватывается

Секретное задание состояния сигнала ядерного объекта. Это состояние не-сигнал, когда объект устанавливается путем вызова FindFirstChangeNotification ()

Когда он чувствует, что деятельность удовлетворяет условие фильтра, сигнал изменения состояния посылаются ожидающим поток. Для того, чтобы продолжить запрашивая инцидент, он должен быть

Явное сбросить начальное состояние, это то, что вы хотите сделать FindNextChangeNotification ().

Синхронные объекты включают в себя «семафоры», «сигнальные огни (семафоры)»,»события (события)„и“критические

Критические секции и т.д., имеет полное описание в файле VC ++ Help. Они имеют различное поведение, но в основном делают

Процесс синхронизации для потоков. С видом на высоком уровне, вы можете думать, что они являются контрольные точки, что нити пересекаются.

Синхронные объекты имеют два состояния: состояние сигнала и состояние без сигнала. Поток останавливается в состоянии без сигнала, после захвата сигнала состояния

Продолжать.

 
Установить параметры

FindFirstChangeNotification () заявление выглядит следующим образом:

HANDLE FindFirstChangeNotification(LPCTSTR lpPathName,

BOOL bWatchSubtree,

DWORD dwNotifyFilter);

LPPathName указатель буфера для контроля имени каталога. Значение BWATCHSUBTREE Boolean определяет, есть ли поддерево в пути.

DWNotifyFilter заставляет вас установить фактическое правило запуска уведомления. Вы можете использовать возможные комбинации флагов на DWNOTIFILTER

Достаточно контролировать, какой тип события файловой системы. Доступные флаги:

 
Подписать

описывать

FILE_NOTIFY_CHANGE_FILE_NAME

Документ создан, удален, перемещение

FILE_NOTIFY_CHANGE_DIR_NAME

Папка установлен, удален, перемещение

FILE_NOTIFY_CHANGE_ATTRIBUTES

Любое изменение атрибутов файлов и папок

FILE_NOTIFY_CHANGE_SIZE

Размер изменений файлов или папок, только тогда, когда какой-либо кэш записывается обратно на диск.

FILE_NOTIFY_CHANGE_LAST_WRITE

Недавнее изменение времени записи файла или папки, только тогда, когда какой-либо кэш записывается обратно на диск.

FILE_NOTIFY_CHANGE_SECURITY

Любой дескриптор безопасности для изменения файлов или папок

 
Очевидно, что эти события будут происходить при наблюдении пути. Например, если вы инициировать вызов:

HANDLE hNotify = FindFirstChangeNotification(__TEXT(«c://»), TRUE,

FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |

FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE);

Создание любого нового файла на диске C, проснись нить ждали этого объекта уведомления. Если задано значение FALSE во втором параметре,

Только изменение в корневой директории драйвера C чувствует. Объект обратного вызова, порожденный FindFirstChangeNotification () находится в несигнала

В состоянии, это означает, что поток, который требуется, чтобы использовать этот объект остановится.

 
каталог мониторов

Теперь мы уже знаем, как построить изменяемый объект уведомления, другой вопрос: Является ли это может полностью контролировать каталог

Деятельность. На самом деле, вы не можете действовать как другие виды деятельности мониторинга, каталог мониторинга потребностей терпения, так что вы должны также подготовить, чтобы захватить любое время

События. С терминологией программного обеспечения, вам необходимо установить цикл в вашем коде. Всякий раз, когда вы закончили мероприятие, вы также должны уведомить нас

Другие события, происходящие одновременно события происходят в следующем появлении препарата или препарата. FINDNEXTCHANGENOTIFICATION () в это время

Использование функций.

BOOL FindNextChangeNotification(HANDLE hChangeHandle);

Ниже приведен фрагмент кода, взятый из образца приложения, показывающая типичное использование функций:

// обратите внимание на логическую защиту вне потока.

// Это код, который принимается на рабочем потоке.

while(g_bContinue)

{

// Ожидание изменения

WaitForSingleObject(hNotify, INFINITE);

// Изменение произошло уведомить главное окно.

// дает ему возможность обновить пользовательский интерфейс программы.

// WM_EX_XXX это сообщение клиента, который прикладывает определен.

PostMessage(ci.hWnd, WM_EX_CHANGENOTIFICATION, 0, 0);

// Подготовка следующего изменения, чтобы прибыть

FindNextChangeNotification(hNotify);

// NB:

// В этой точке, объект синхронизации инкапсулируется пакета HNOTIFY в несигнала, таким образом, поток выполняется снова.

// WaitForSingleObject (), он остановится, пока новая смена не происходит, и становится состоянием сигнала

}

Как видно из вышесказанного, нет ни одного события, чтобы завершить цикл внутри циркуляции. G_bcontinue логическая переменная является полный спектр переменных вне потока, то есть

Скажем, этот код предполагает две темы: основные темы, приложения и рабочие темы, связанные с объектами уведомления.

Так как предполагается, этот код будет выполняться после вызова FindFirstChangeNotification (), он остановится после выполнения секции.

WaitForSingleObject () вызовы, так как объект уведомления в это время стал состоянием без сигнала. При встрече уведомления HNOTIFY

Когда происходит событие статуса, статус объекта переходит в состояние сигнала, выполняет продолжение, и бросает сообщение клиента к указанному окну, придать ему

Возможность обновить пользовательский интерфейс или сделать дальнейшие процессы, а затем снова остановка, ожидая новое событие. передача

FindNextChangeNotification () затем содержится в статусе объекта синхронизации в HNotify, и изменяет обратно в состояние не-сигнала.

При обработке объекта уведомления, мудрый выбор, чтобы изолировать код для всех ожидающих событий с различными рабочими потоками. Это позволит избежать

Основная программа является неопределенной. Если вы не хотите, многопоточные приложения, вы должны использовать MsgWaitForMultipleObjects () вместо

WaitForSingleObject (), чтобы ждать сообщения или события. Кроме того, можно установить несколько объектов уведомлений одновременно. Например, вам может понадобиться

Различные каталоги на разных дисках отдельно, если вам это нужно, WaitForMultipleObjects () может помочь вам

Синхронизировать все объекты уведомления вместе.

 
Остановить мониторинг

объект уведомления релиз должен вызвать FindCloseChangeNotification (), единственная переменная, переданная выполнена

FindFirstChangeNotification () установлены ручки:

BOOL FindCloseChangeNotification(HANDLE hChangeHandle);

 
Общий пример

Давайте посмотрим на пример приложения, эта программа концептуальное отображение работы детектора позади экрана. Эта программа заставляет вас выбрать

Путь и установить объект уведомления для мониторинга всего поддерева, все изменения, уведомляются в разных потоках. Ощущение каждого события

Существует сообщение, чтобы бросить его в главном окне приложения. В качестве демонстрации, мы просто добавить строку, содержащую текущее время в список отчетов. а также

Вам может потребоваться дополнительная обработка в реальной работе. Работа нить принимает дескриптор окна и контроль пути, оконная ручка используется для отправки

Интерес к главному окну приложения, передача данных с использованием определенных пользователем структур. Пользовательский интерфейс программы показан на рисунке:

                  
При нажатии на кнопку, объект уведомления устанавливается с помощью свойства названных выше:

FILE_NOTIFY_CHANGE_FILE_NAME,

FILE_NOTIFY_CHANGE_DIR_NAME,

FILE_NOTIFY_CHANGE_ATTRIBUTES,

FILE_NOTIFY_CHANGE_SIZE

Ниже приведен код, который Вы должны присоединиться кадр:

// данные

HICON g_hIconLarge;

HICON g_hIconSmall;

Bool g_bcontinue; // должен быть установлен в FALSE в WinMain ()

const int WM_EX_CHANGENOTIFICATION = WM_APP + 1;

/ / Pass данные клиента к теме

struct CUSTOMINFO

{

HWND hWnd;

TCHAR pszDir[MAX_PATH];

};

typedef CUSTOMINFO* LPCUSTOMINFO;

В приведенном выше коде мы явно объявить константу WM_EX_CHANGENOTIFICATION сообщение. Как правило, определение констант, как Windows,

В то время интереса, функция RegisterWindowMessage () следует использовать для обеспечения уникального сообщения номера системы. Однако, в соответствующих отдельных приложениях,

Если нет широковещательного сообщения, использовать явные константы выписки WM_APP на основе безопасно. WM_APP является основной константой, после него

Константы не могут вступать в противоречие с сообщениями системы Windows. Единственное приключение можно конфликт с сообщениями клиентов из других приложений, это в данном случае.

Это не может произойти в ребенке.

Существует быть добавлены в App_dlgProc (), который пробуждается, когда объект уведомления чувствует изменения, вам нужно это новый процессор.

Небольшое изменение производится на процессоре IDCANCEL прекратить поток, когда программа будет закрыта.

BOOL CALLBACK APP_DlgProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)

{

switch(uiMsg)

{

case WM_INITDIALOG:

OnInitDialog(hDlg);

break;

case WM_EX_CHANGENOTIFICATION:

UpdateView(hDlg);

break;

case WM_COMMAND:

switch(wParam)

{

case IDOK:

OnOK(hDlg);

return FALSE;

case IDCANCEL:

g_bContinue = false;

EndDialog(hDlg, FALSE);

return FALSE;

}

break;

}

return FALSE;

}

Кроме того, этот процессор по-прежнему вызывая OnOK () для кнопки «Установить Notification Object», потому что я не изменил идентификатор кнопки, но только

Метка изменяется.

void OnOK(HWND hDlg)

{

TCHAR szDir[MAX_PATH] = {0};

GetDlgItemText(hDlg, IDC_EDIT, szDir, MAX_PATH);

SHInstallNotifier(hDlg, szDir);

}

OnOK () вызывает функцию shinstallNotifier (), эта функция создает объект CustomInfo и передает потоки вызова уведомит ()

функция:

HANDLE SHInstallNotifier(HWND hwndParent, LPCTSTR pszDir)

{

DWORD dwID = 0;

CUSTOMINFO ci;

ZeroMemory(&ci, sizeof(CUSTOMINFO));

ci.hWnd = hwndParent;

lstrcpy(ci.pszDir, pszDir);

// Создать рабочую нить

g_bContinue = true;

HANDLE hThread = CreateThread(NULL, 0, Notify, &ci, 0, &dwID);

return hThread;

}

Notify () сам по себе существует, чтобы создать место для вызова функции FINDXXXCHANGENOTIFICATION (), и сохранить указанное дерево каталогов в цикле

Монитор:

DWORD WINAPI Notify(LPVOID lpv)

{

CUSTOMINFO ci;

ci.hWnd = static_cast<LPCUSTOMINFO>(lpv)->hWnd;

lstrcpy(ci.pszDir, static_cast<LPCUSTOMINFO>(lpv)->pszDir);

HANDLE hNotify = FindFirstChangeNotification(ci.pszDir, TRUE,

FILE_NOTIFY_CHANGE_FILE_NAME |

FILE_NOTIFY_CHANGE_DIR_NAME |

FILE_NOTIFY_CHANGE_ATTRIBUTES |

FILE_NOTIFY_CHANGE_SIZE);

if(hNotify == INVALID_HANDLE_VALUE)

{

SPB_SystemMessage(GetLastError());

return 0;

}

while(g_bContinue)

{

WaitForSingleObject(hNotify, INFINITE);

PostMessage(ci.hWnd, WM_EX_CHANGENOTIFICATION, 0, 0);

FindNextChangeNotification(hNotify);

}

FindCloseChangeNotification(hNotify);

return 1;

}

Когда событие становится событием сигнала, сообщение типа WM_EX_CHANGENOTIFICATION посылается, в результате чего вызова функции в updateView ():

void UpdateView(HWND hDlg)

{

TCHAR szTime[100] = {0};

HWND hwndList = GetDlgItem(hDlg,IDC_LIST);

GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, szTime, 100);

AddStringToReportView(hwndList, szTime, 1);

}

Вы можете увидеть этот код использует функцию AddStringToreportView (), которая является сектором мы разработали в предыдущей главе отчета

Функция наблюдения. Его функция компаньон MAKEREPORTVIEW (), который вызывается в OnInitDialog (), чтобы установить наблюдение отчета.

void OnInitDialog(HWND hDlg)

{

// Установить значок T / F большой / маленький значок)

SendMessage(hDlg, WM_SETICON, FALSE, reinterpret_cast<LPARAM>(g_hIconSmall));

SendMessage(hDlg, WM_SETICON, TRUE, reinterpret_cast<LPARAM>(g_hIconLarge));

LPTSTR psz[] = {__TEXT(«Date and Time»), reinterpret_cast<LPTSTR>(400)};

MakeReportView(GetDlgItem(hDlg, IDC_LIST), psz, 1);

}

Для того, чтобы добавить #include resource.h в верхней части исходного файла, и скомпилировать это приложение. После запуска этого приложения, вы заметите, что если

Фрукты копирование файлы, вы можете получить два уведомления, удалить может иметь три уведомления, если все флаги будут удалены, только сохранены

File_notify_change_file_name и повторите операцию копирования, количество уведомлений сводится к 1, потому что мы больше не имеют свойства и размеры

Изменить интерес. Тем не менее, есть еще два уведомления при удалении операций. Для того, чтобы понять, почему, попробуйте удерживать нажатой кнопку Shift.

Удаление файлов — вы увидите, что есть только одно уведомление в настоящее время. В этом случае удаление файла уничтожается непосредственно вместо того, чтобы экономить

«Рециркуляция станция». Таким образом, один из двух шагов при обычном удалении файла удаляются в «Корзину», а затем удалите файл.

Просто удалите файлы генерировать уведомления, когда файлы фактически удалены.

 
Детектор и объект уведомления

Стася, поведение детектора является таким же, как этим приложение: он задает объект уведомления в отображаемой папку, каждый получил

К уведомлению об изменении событий, он перезагружает эту папку, чтобы ответить на эти изменения. Подумайте об этом, вы узнаете уведомление.

Механизм объекта точно настроен на необходимость детектора.

Детектор не мониторинга рутина файловой системы, она должна знать, если некоторые вещи изменились в наблюдаемом текущей папки.

И изменение влияния данных отображения: файлы и вложенные папки имя, атрибуты, размер, дата, безопасность и т.д. Независимо от того, как точная операция,

Важно, что-то произошло. Этот механизм, как представляется, является хорошим компромиссом в системе и производительности детектора.

 
Discluding процедуры мониторинга файловой системы

Так же, как мы уже видели, самые большие недостатки объекта уведомления является то, что информация, которая может быть предоставлена ​​в случае фактического очень бедна,

Зная объект подобен противоугонных и пожарной сигнализации: Когда кольцо звонит, вы не знаете, что он был украден или уволят, или оба случаются.

Это ограничение затрудняет (не невозможно) установить утилит мониторинг, чтобы нам знать, что программа во всей системе файловой системы

Какие файлы обрабатываются.

Рассмотрим решение этой задачи с помощью метода icopyhook расширения оболочки. Даже это большой прогресс, но

Существует еще некоторое расстояние от нашей конечной цели.

 
Описание Windows NT

До сих пор мы не обсуждали различные операционные системы. Вы можете думать, в Windows95, Windows98 и

Там нет Основного различия между Windows NT, но на самом деле, как мы надеемся, появится в Windows NT4.0 или выше.

Выход Windows NT в Win32 SDK и объясняет функцию ReadDirectoryChangesW (), он имеет аналогичный

Прототип FindFirstChangeNotification (), но есть большая разница: он использует специальную информацию и то, что требуется, чтобы использовать.

Информация Активное лицо заполняется буфер.

Для получения более подробной информации о ReadDirectoryChangesW () функция и объект уведомления, как правило, в данных Advanced Windows

Нашел.

 
Функция SHCHANGENOTIFY ()

При изменениях в системе, сам детектор может чувствовать их (особенно изменение файла), но он не должен отображаться.

Какие изменения информируют программа выполнения. Для того, чтобы сделать это проще, оболочка API определяет функцию ShchanGenotify (), его единственная цель

Это уведомить детектор, и некоторые настройки системы были изменены. Концепция, Shchangenotify () производит тот же эффект, что и объект уведомления

Тем не менее, следует другой логике. Таким образом, внешнее приложение может быть использовано для информированного детектора некоторых изменений, производимых. В ответ

В этом уведомлении, детектор будет обновить пользовательский интерфейс. Это очевидный пример, который показывает, что мы уже упоминали ранее, и оболочка

Канал’.

 
Вызов функции ShchanGenotify ()

Эта функция определена в shlobj.h, ниже его прототип:

void WINAPI SHChangeNotify(LONG wEventId,

UINT uFlags,

LPCVOID dwItem1,

LPCVOID dwItem2);

Параметр WeventID указывает случае системы оповещения, которая получает набор из одного или более возможных значений. Наиболее общий список значений выглядит следующим образом:

 
мероприятие

описывать

SHCNE_ASSOCCHANGED

Файл не связан изменился, не указано, которая указана.

SHCNE_NETSHARE

Локальная папка общего доступа, которая вызывает значок для изменения. Dwitem1 должен включать в себя имя папки, имя папки может быть полный путь к файлу или

PIDL (см. Ниже)

SHCNE_NETUNSHARE

не локальная папка больше не разделяет. Это приводит к тому, значок для изменения. Имя папки (полное имя пути или PIDL) входит в DwItem1.

SHCNE_SERVERDISCONNECT

Этот компьютер был отключен от сервера. Dwitem1 содержит имя сервера.

SHCNE_UPDATEDIR

Содержание дается в папку изменилось, но это изменение не влияет на файловую систему. Dwitem1 включает в себя имя папки (полное имя или

PIDL)。

SHCNE_UPDATEIMAGE

Значок в списке образа системы изменилась. Dwitem1 содержит индекс значка. Это приводит к тому, детектор для обновления пользовательского интерфейса, а также при необходимости рисовать новую картину.

Подписать. Все иконки, используемые детектором, хранятся в полной структуре, называемой «системы список изображений» или в «детектора кэш внутренней значок»

Отказ Как получить Handle этого списка изображений в главе 4.

SHCNE_UPDATEITEM

Nonfold клип изменился. Dwitem1 включает в себя полное имя файла или PIDL.

 
Этот список событий не является полным, мы дадим оставшийся логотип позже. Полный список логотипа может быть передан в библиотеку MSDN.

SHCHANGENOTIFY () зависит от идентификатора события, указанного в переменной WeventID, DwItem1 и

Dwitem2 переменные содержат значение Событийного. Параметр UFLAGS используется для представления типа dwitem1 и dwitem2. Он может представлять собой число типа DWORD

(SHCNF_DWORD), PIDL (SHCNF_IDLIST), строка (SHNCF_PATH) или имя указателя (SHCNF_PRINTER). Кроме того, uflags также относится к

Если функция должна ждать уведомления, подлежащая обработке. постоянная SHCNF_FLUSH ожидает, shcnf_flushnowait средства, не дожидаясь,

Функция возвращает немедленно.

 
Функция SHCHANGENOTIFY ()

Функция shchangenNotify () предлагается в качестве дополнительной функции объекта уведомления. Другими словами, это действительно абсолютно необходимые функции

Отказ Эта функция стремится обеспечить ту же функцию, что и объект уведомления (хотя другая логика), она не ограничивается парами файловой системы

Слон. Как мы уже видели в главе 5, Windows Shell состоит из файловых объектов, и большинство объектов файлов отображаются в

Физическая сущность файловой системы не всегда так. Например, объект файла «Мой компьютер» и «принтер» не имеют соответствующую цели.

записывать. Кроме того, даже если у вас есть папка, подключенная к каталогу, элементы, которые они содержат, не обязательно файл. Другими словами, вы можете

Там нет никакого влияния на файловой системе, чтобы добавить новые элементы (или удалять элементы) в папку. Как детектор почувствовать эти изменения в это время?

После того, как глубокое понимание этой проблемы, мы запутались, можно разработать систему мониторинга

Как насчет программ? Позже мы увидим, что пространство имен проходят через интерфейс в стиле папок могут быть использованы для отображения много. Например,

Интернет клиент SDK имеет пример RegView, добавление нового узла в иерархии детектора, так же, как обычная папка

Характеристики характеризуются содержанием включенного в системном реестре, а на самом деле содержание одного или двух файлов. Как почувствовать этот детектор или другой инструмент

Изменения в? Вы можете написать программное обеспечение для подключения события реестра, однако, если кто-то заменяет другое расширение пространства имен

REGVIEW и сделать совершенно другую работу, что я должен делать?

Пока операция выходит за рамки традиционной файловой системы, мы должны изменить уведомление пути. Это уже не детектор себя чувствует

Изменение, но приложение было отправлено уведомление. Это путь Shchangenotify (). Некоторые для вызова

Shchangenotify (), определенные события могут быть избыточными, например, shcne_create событие не может использовать — это представляет собой

Новый файл, но детектор уже знает, что это событие, ссылаясь на объект уведомления. С другой стороны, если этот элемент не является объектом файловой системы,

Вы должны вызвать ShchanGenotify (), чтобы сделать детектор знать это изменение:

 
SHChangeNotify(SHCNE_CREATE, SHCNF_IDLIST, pidl, NULL);

 
SHCHANGENOTIFY () Другие события

Теперь основное понятие функции Shchangenotify () немного понятно, но он также нуждается в дополнительные добавки.

Ниже перечислены все события, которые могут быть переданы в функцию через переменную WeventID:

 
мероприятие

описывать

SHCNE_ATTRIBUTES

Документ или атрибут папки изменяется. Dwitem1 это имя файла или папки (полное имя пути или PIDL).

SHCNE_CREATE

Объект файл был создан. Dwitem1 это имя объекта файла.

SHCNE_DELETE

Объект файл был удален. Dwitem1 это имя объекта файла.

SHCNE_DRIVEADD

Добавлен диск. Dwitem1 является корнем привода, вида: C: /.

SHCNE_DRIVEADDGUI

Добавьте диск и требует нового окна. Dwitem1 является корнем привода, вида: C: /.

SHCNE_DRIVEREMOVED

Удалить диск. Dwitem1 является корневой каталог диска.

SHCNE_FREESPACE

Объем свободного места на диске. Dwitem1 является корнем привода, вида: C: /.

SHCNE_MEDIAINSERTED

Носитель информации вставлен в дисковод. Dwitem1 является корнем привода, вида: C: /.

SHCNE_MEDIAREMOVED

Носитель данных был удален из дисковода. Dwitem1 является корнем привода, вида: C: /.

SHCNE_MKDIR

Была создана папка. Dwitem1 это имя объекта файла.

SHCNE_RENAMEFOLDER

Папка была переименована. Dwitem1 старое название папки, Dwitem2 новое имя папки. Название может быть полное имя или PIDLS.

SHCNE_RENAMEITEM

Переименовать объект файла. Dwitem1 старое название объектный файл, Dwitem2 новое имя объекта файла.

SHCNE_RMDIR

Удаленный файловый объект. Dwitem1 это имя объекта файла.

 
Использование ShchanGenotify ()

Функция shchangenotify () очень полезно, когда вы начнете писать расширение пространства имен, потому что он скрывает вас к детектору.

Элемент или папка не может быть тот факт, что реальный объект файловой системы. В главе 16 мы будем развивать расширение пространства имен.

Программа, это информация о системе отображения в системе отображения контента в системе отображения контента в самом окне. Расширяя сочетание полных крюков,

Программа может воспринимать любое новое окно, и использовать флаг SHCNE_CREATE для вызова ShchanGenotify () и позволит детектор

Обновить содержимое этой папки клиента.

Хотя мы уже говорили во второй главе, мы до сих пор не хотят, чтобы сосредоточиться на крючке WINDOWS. Вы можете получить больше о библиотеке MSDN, чтобы получить больше

Информация.

Вместо этого общие приложения развиваются редко shchangenotify () услуг. Динамические типы изменения файла ассоциации, возможно, потребуется сделать

Использование — то есть, он изменяет программу для обработки специальных документов класса, который хранит местоположение, указанное ниже реестра:

HKEY_LOCAL_MACHINE

/Software

/Microsoft

/Windows

/CurrentVersion

/Extensions

Для того, чтобы уведомить обновление детектора, вы можете позвонить:

SHChangeNotify(SHCNE_ASSOCCHANGED, 0, NULL, NULL);

пространство для хранения Вторжение оболочки

Если вы опытный программист Win32, вы будете знать, что каждый процесс работает в своем адресном пространстве,

И только в этом адресном пространстве, адрес памяти имеет постоянное значение. Например, вы не можете унаследовать, окно, созданное другим процессом

Поскольку адрес нового процесса окна может указывать только на вас в другом адресном пространстве. На самом деле, SetWindowLong ()

Функциональные блоки это усилие, если вы попытаетесь сделать это, он возвращает ноль.

Но сделать свой программный код карты в другой процесс приложения действительно возможно, что требует несколько шагов. Microsoft

Причина, почему он останавливается, потому что он создает потенциальные ошибки, чем при использовании других более простых технологий программирования, однако, доступ к другому приложению

Адресное пространство является безопасным, так долго, как вы знаете, что вы собираетесь делать, что вы должны сделать, и все темы. Прорваться через границу

Там нет никаких препятствий и по существу дела. Как и использование указателей — может вызвать ошибки, если она не используется должным образом.

Shell представляет собой процесс Win32, который вы можете использовать один и тот же путь для вторжения в приложении NOTEPAD, чтобы вторгнуться в пространстве памяти. Почему

Что нам нужно, чтобы вторгнуться в оболочку, это то же самое, как вы вводите любой другой процесс Win32 или Win16: необходимость изменения (или фильтр) один

Поведение программы. Вы заметили, что копия NOTEPAD имеет возможность поддерживать некоторые межсессионные настройки. Запустите Блокнот,

И откройте режим «Word Heavy Stack», этот параметр будет постоянно храниться, и он будет восстановлен каждый раз, когда вы открываете. Если вы хотите быть в Windows95 или

Эта функция реализована под Windows98, вы должны настроить стандартное поведение блокнота. Другими словами, вам нужно вторгать свой код.

Его адресное пространство.

В оставшейся части этой главы мы покажем три способа ввода в адресное пространство детектора. Один из них традиционная технология SDK

Хирургия, такая как крючки и подклассы. Второе исследование функции API оболочки SHLOADINPROC (). Обе технологии могут быть в Win32

Работа на платформе, кроме Windowsce. Третий выбор доступен только в 4.71 или выше, а детектор разведки и т. Е. Все характеристики: просматривать

Вспомогательные объекты.

 
Вынужден в пути

Когда я понимаю, что нет никакого способа, чтобы создать папку в меню, мы рассмотрим окно детектора подкласса. Я не верю, что мне.

Это единственный человек, который не нашел комбинированную сон ключ, я пытался добавить клавиатуры ускоритель, который быстро установил новую папку. Даже

База знаний списка ярлыков клавиатуры Windows не относится к комбинации новых папок. Я не знаю, что другие, я послал это.

Все эти работы довольно не удалось: щелкните правой кнопкой мыши (или щелкните меню «Файл»), затем выберите два элемента и, наконец, нажмите.

Моя цель состоит в том, чтобы создать небольшое приложение, поместите его в папке «Пуск», он устанавливает общесистемный крюк,

Для поддержания определенного класса Window Estake Track, в этой проблеме этот класс окна является окном детектора «ExcreeWlass».

Мы использовали стек Spy ++ Senting Window, чтобы найти это имя класса.

Как только ручка окна детектора получается, мы можем установить крючок клавиатуры к определенному потоку для установления этого окна. второй

Крюк, отвечающий на активность клавиатуры и установить папку, когда клавиатура соответствует указанному правилу. Эта задача может быть разбита на две части:

Введите детектор

Создайте папку с тем же методом, что и детектор

В Win32 нет большого способа сопоставить свой код в другой адрес в процессе. Если вы хотите, чтобы ваш код совместим с

Windows9x и Windows, только одна возможность: установить крючок в диапазоне системы.

 
Зачем использовать крючки

Даже если окончательная цель не является крюком, а простое окно типа земли, если это окно принадлежит другому процессу, сделайте это

Прежде чем работать, вы также должны установить крючок. Независимо от того, какой крючок вы используете, проблема в том, что она применяется ко всем нитям системы.

Что это.

Такие, как концепция, представленная во второй главе, используйте крючки для уточнения функции обратного вызова, когда определенные (связанные с этим крюком)

Система просыпается эта функция, когда происходит событие. Если вы хотите контролировать все пробеги во всех прогонах, функция должна находиться в DLL, потому что

Система должна сопоставить ее в эти процессы.

 
Введите внутреннюю часть детектора

Наша программа будет искать окно (специальное, в поисках детектора Windows). Процесс крюка типа WH_CBT потребностей

Программа устанавливается при запуске программы, чтобы вызвать эту функцию при выполнении какой-либо деятельности (устанавливать, удалять, активации и т.д.) в окне:

g_hShellHook = SetWindowsHookEx(WH_CBT, ShellDll_MainHook, g_hThisDll, 0);

Этот крюк должен быть удален при выходе:

if(g_hShellHook != NULL)

UnhookWindowsHookEx(g_hShellHook);

Очевидно, что во всей системе есть крючок, которая влияет на его производительность. Крючок в любом системном диапазоне, потому что они существуют

Повлияет на производительность системы. Это делает систему сделать дополнительную работу, которая, несомненно, эквивалентна снижению производительности системы. Поэтому мы рекомендуем, чтобы система

Крючок должен быть максимально небольшим. Мне минимум, что значительно снижает риск потери производительности. Процесс этого крюка выглядит следующим образом:

LRESULT CALLBACK ShellDll_MainHook(int nCode, WPARAM wParam, LPARAM lParam)

{

TCHAR szClass[MAX_PATH] = {0};

// Любой типичный запуск любого процесса крюка

if(nCode < 0)

return CallNextHookEx(g_hShellHook, nCode, wParam, lParam);

// Система строит окно. Обратите внимание, что крюк пробуждается из этого кода Createwindowex () и Createwindowex ().

/ / В данный момент окно уже существует, HWND эффективен, даже если мы все еще находимся в середине процесса.

if(nCode == HCBT_CREATEWND)

{

// Получить HWND окна

HWND hwndExplorer = reinterpret_cast<HWND>(wParam);

/ / Сравнить «Explorewclass» и установить крючок клавиатуры

GetClassName(hwndExplorer, szClass, MAX_PATH);

if(!lstrcmpi(szClass, __TEXT(«ExploreWClass»)))

InstallKeyboardHook(hwndExplorer);

}

return CallNextHookEx(g_hShellHook, nCode, wParam, lParam);

}

Этот код выполняется всякий раз, когда установлено окно. Если имя класса окна соответствует имени класса окна зонда (для Explorewclass), ключ установки

Лоток, на данный момент, мы вошли в адресное пространство детектора. Обратите внимание, что крючок «клавиатуры» может быть частичной частью для обнаружения

Поток устройства, у него есть Explorewclass окна класса, не нужно зацепить активность клавиатуры по всей системе, потому что когда мы строим новую папку

Когда входной фокус, естественно, на детекторе (мы дальше объясним дальше).

 
Как построить новую папку

Для того чтобы сопоставить код крючка к адресному пространству процесса, достаточное состояние — это разбудить диапазон системы от процесса.

Суб процесс. Теперь эта проблема сводится к созданию новой папки. Очевидно, мы хотим получить тот же способ ручных привычек сборки

Отказ Таким образом, самый простой способ — точно повторить операцию, когда детектор использует меню «New | папка».

Возможно, вам придется спросить, почему вам не нужно выбирать метод, который вы обсуждали ранее — то есть, почему бы вы не использовали API оболочки, получить текущий каталог и

Создание нового каталога. Причина в том, что эти методы были недействительными в этом случае. Прежде всего, откуда вы знаете, какой из них отображается в данный момент?

Папка? GetCurrentDirectory () возвращается имя является неполным. Во-вторых, многие специальные папки не разрешается строить вложенные папки

Если это вызовет неприятности.

Я обсуждал принцип создания новой папки, когда детектор установил новую папку при ответе на сообщение WM_COMMAND отправляется в главном окне. Для удобства исследований

Я написал программу, subcatenate окна ExplorewClass для определения его параметров при обработке сообщения WM_COMMAND каждый раза. Проходить

После этого метода, мы находим, что вы хотите сделать запрос на зонд, чтобы создать новую папку, вам нужно всего лишь отправить это окно следующим образом:

PostMessage(hwndExplorer, WM_COMMAND, 29281, 0);

Magic Number 29281 является идентификатор | пункт меню «Новая папка». Это неофициальная информация, и она может быть изменена в новой версии оболочки.

Тем не менее, в настоящее время он работает с Windows 9X и Windows NT. Если это число не будет изменено в будущем, если сущностной структуры оболочки

Вам только нужно просто найти новый идентификационный номер. Это число никогда не меняется от 4.00 до 4.71.

После установки хука клавиатуры, оболочка может создать новую операцию папки в ответ на кнопки. Мы выбрали клавиши F12 — нет ничего особенного

Причина может свободно использовать любые другие ключи. Когда процесс крючка клавиатуры чувствует, что F12 нажата, она просто восстанавливает окно детектора.

И отправить сообщение.

 
Пример программы

Как упоминалось выше, образец программы неизбежно делится на две части: DLL и исполняемым. Первым из них является исходным кодом программы DLL код, в том числе

Два крючка, он основан на фреймворке DLL, мы назвали Exphook Engineering (проект). Полная переменная и объявление функции

Exphook.h файл:

/*—————————————————————*/

// Фестиваль Prototype

/*—————————————————————*/

HHOOK g_hShellHook;

HHOOK g_hKeybHook;

HWND g_hwndExplorer;

void InstallKeyboardHook(HWND hwnd);

void APIENTRY ShellDll_Hook();

void APIENTRY ShellDll_Unhook();

LRESULT CALLBACK ShellDll_KeybHook(int nCode, WPARAM wParam, LPARAM lParam);

LRESULT CALLBACK ShellDll_MainHook(int nCode, WPARAM wParam, LPARAM lParam);

Естественно, реализация прототипов в Exphook.cpp, эти функции просто достичь принципов, которые мы обсуждали:

/ / Установить крюк, чтобы почувствовать начало детектора

void APIENTRY ShellDll_Hook()

{

g_hShellHook = SetWindowsHookEx(WH_CBT, ShellDll_MainHook, g_hThisDll, 0);

}

void APIENTRY ShellDll_Unhook()

{

if(g_hKeybHook != NULL)

UnhookWindowsHookEx(g_hKeybHook);

if(g_hShellHook != NULL)

UnhookWindowsHookEx(g_hShellHook);

}

// shelldll_mainhook () крюк в списке вставляется в этот код

LRESULT CALLBACK ShellDll_KeybHook(int nCode, WPARAM wParam, LPARAM lParam)

{

// Любой процесс крюк типична

if(nCode < 0)

return CallNextHookEx(g_hKeybHook, nCode, wParam, lParam);

// Общие Этот код выполняется, когда клавиатура нажата и отпущена. Информация преобразования состояния хранится в высших два цифрах LPARAM

/ / Таким образом, мы только регулируем операцию клавиатуры.

if((lParam & 0x80000000) || (lParam & 0x40000000))

return CallNextHookEx(g_hKeybHook, nCode, wParam, lParam);

if(wParam == VK_F12)

{

// получить окно детектора ручку и отправлять сообщения.

g_hwndExplorer = FindWindow(«ExploreWClass», NULL);

PostMessage(g_hwndExplorer, WM_COMMAND, 29281, 0);

}

return CallNextHookEx(g_hKeybHook, nCode, wParam, lParam);

}

/ / Установить крюк клавиатуры

void InstallKeyboardHook(HWND hwnd)

{

g_hwndExplorer = hwnd;

DWORD dwThread = GetWindowThreadProcessId(g_hwndExplorer, NULL);

g_hKeybHook = SetWindowsHookEx(WH_KEYBOARD, ShellDll_KeybHook,

g_hThisDll, dwThread);

}

Для того, чтобы вывести эту библиотеку к функции мы нуждаемся, вы также должны добавить эти поездки в .def файл:

EXPORTS

ShellDll_Hook @2

ShellDll_Unhook @3

ShellDll_KeybHook @4

ShellDll_MainHook @5

Это DLL нам нужно. После того, как соединение компиляции перемещается в основную программу, затем добавить значок после области уведомлений панели задач, легко

Этот крюк легко выгружаются. В дополнение к созданию значка, сама основная программа также содержит установки и удаления функции WH-CT крюк. В связи с этим приложением

Характеристики порядка не как общее применение. Сначала установить диалог на основе приложения EXPFOLD, добавьте

#include заявление, в том числе определения функции DLL:

/*—————————————————————*/

раздел / / Содержит

/*—————————————————————*/

#include «ExpFold.h»

#include «ExpHook.h»

Во-вторых, две новые константы: Во-первых, сообщение клиента, когда значок лотка щелкают, то отправленное сообщение, а затем ID:

// Data

Const INT WM_MYMESSAGE = WM_APP + 1; // Лоток значок сообщения

const int ICON_ID = 13;

HICON g_hIconLarge;

HICON g_hIconSmall;

HINSTANCE g_hInstance;

Новый полный переменный используются для хранения Ручки экземпляра приложения, которое необходимо, когда он позже назвали LoadMenu (). Вот WinMain ()

Необходимость изменения делают:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevious,LPTSTR lpsz, int iCmd)

{

/ / Сохранить полные данные

g_hInstance = hInstance;

g_hIconSmall = static_cast<HICON>(LoadImage(hInstance, «APP_ICON»,

IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),

GetSystemMetrics(SM_CXSMICON), 0));

// Создание Нетрадиционные диалогов, чтобы получить сообщения от графика

HWND hDlg = CreateDialog(hInstance, «DLG_MAIN», NULL, APP_DlgProc);

// Отобразить значок в трее области

TrayIcon(hDlg, NIM_ADD);

/ / Установить детектор крюк

ShellDll_Hook();

MSG msg;

while(GetMessage(&msg, NULL, 0, 0))

{

if(!IsDialogMessage(hDlg, &msg))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

// Удаление крюк

ShellDll_Unhook();

// Удалить значок

TrayIcon(hDlg, NIM_DELETE);

DestroyWindow(hDlg);

DestroyIcon(g_hIconSmall);

return 1;

}

В отличие от отображаемого диалогового окна, это приложение создает диалоговое окно невидимым путем вызова CreateDialog () вместо DialogBox ()

Диалог процесс выглядит следующим образом:

BOOL CALLBACK APP_DlgProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)

{

switch(uiMsg)

{

case WM_COMMAND:

switch(wParam)

{

case IDCANCEL:

PostQuitMessage(0);

return FALSE;

}

break;

case WM_MYMESSAGE:

if(wParam == ICON_ID)

{

switch(lParam)

{

case WM_RBUTTONUP:

ContextMenu(hDlg);

break;

}

}

break;

}

return FALSE;

}

Функция TrayIcon () вызывается после того, как диалоговое окно установлено, что отображает значок на панели задач лотка и удаляет его при выходе:

// Отобразить значок в трее области

BOOL TrayIcon(HWND hWnd, DWORD msg)

{

NOTIFYICONDATA nid;

ZeroMemory(&nid, sizeof(NOTIFYICONDATA));

nid.cbSize = sizeof(NOTIFYICONDATA);

nid.hWnd = hWnd;

nid.uID = ICON_ID;

nid.uFlags = NIF_TIP | NIF_ICON | NIF_MESSAGE;

nid.uCallbackMessage = WM_MYMESSAGE;

nid.hIcon = g_hIconSmall;

lstrcpyn(nid.szTip, __TEXT(«Explorer’s Hook»), 64);

return Shell_NotifyIcon(msg, &nid);

}

Наконец, функция Контекстное () вызывается, когда пользователь нажимает на иконку в трее. Для нормально, вам нужно добавить меню типа IDR_MENU

В рамках проекта, вы должны включать в себя пункт «закрыть» в меню, и его идентификатор IDCANCEL.

// Отображение соответствующего меню значка

void ContextMenu(HWND hwnd)

{

POINT pt;

GetCursorPos(&pt);

HMENU hmenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MENU));

HMENU hmnuPopup = GetSubMenu(hmenu, 0);

SetMenuDefaultItem(hmnuPopup, IDOK, FALSE);

SetForegroundWindow(hwnd);

TrackPopupMenu(hmnuPopup, TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, NULL);

SetForegroundWindow(hwnd);

DestroyMenu(hmnuPopup);

DestroyMenu(hmenu);

}

 
Программа деятельности

Содержит #include «resource.h» и после компиляции программы, подключения библиотеки exphook.lib, будет. EXE и .DLL два текста

Часть. Затем создать ярлык для выполнения файлов, скопируйте этот ярлык в папку «запускающей».

                                         
Эта программа может быть удалена с помощью щелчка правой кнопки мыши на иконке в трее и выберите «Закрыть» удаление. До тех пор, как он установлен, вы можете подключить каждое окно детектора.

И установить крюк клавиатуры в потоке ответа, этот процесс клавиатуры отыскивает F12 и отправить сообщение в соответствующее окно.

 
Введите оболочки пространства для хранения

Есть два способа, чтобы поместить внешний код в адресное пространство оболочки. Вторжение (мы уже видели), и приглашение (дружеская вечеринка

Закон только тогда, когда мы можем найти способ сделать это). В первом режиме, основная программа не знает, что он работает. С другой стороны, после того, как

Один из способов основной программы непосредственно контролирует возникновение всего.

Оболочки Windows через приглашение, а не вторжение, предоставляя возможность для входа в пространстве для хранения — SHELL API

Для функции часто не обращая внимания, ShLoadInproc (), который определен в shlobj.h и имеет удивительные возможности. Тем не мение,

Описание этой функции действительно очень плохо, в соответствии с только информацией, вы можете сомневаться воображают ли эта функция. просто

Для того, чтобы проиллюстрировать свою способность, в этом разделе мы намерены создать пример DLL, этот пример позволяет нам восстановить и заменить Windows,

Кнопка Пуск. Перед началом этой задачи, это будет необходимо.

 
Функция SHLoadInproc ()

Под цельным корпусом, функция shloadinproc () помещает свой модуль в адресное пространство оболочки. Это на самом деле вы

Цель напряженной работы в предыдущем разделе. ShloadInProc () загружает модуль и сохраняет его в покое. Ниже Интернет

Описание этого клиентского SDK:

WINSHELLAPI HRESULT WINAPI SHLoadInProc(REFCLSID rclsid);

Экземпляр указанного объекта устанавливается в пределах ассоциированного процесса оболочки. В случае успеха, возвращение к NoError, в противном случае возвращает результат ошибки определения OLE.



rclsid

CLSID класса объекта должен быть создан.

 
Эта информация является абсолютно правильной, и проблема заключается в том, что не существует структура «класс объектов». Какие интерфейсы должны быть реализованы, какие специальные

Что специальное правило должно следовать, что может быть сделано без определенного интерфейса, если вам не требуется специальный интерфейс, каким образом начинается объект

Работа.

Все эти вопросы не ответили на информацию. Честное слово, мы не можем понять, как сделать эту функцию.

 
Минимальный COM объект

Функция shloadInproc () является самым быстрым и наиболее эффективным способом ввести свой код в адресное пространство SHELL, но это поколение

Код должен быть COM объект. Однако для того, чтобы исследовать эту функцию, мы не должны строить полный СОМ-объект — только часть части

COM и DLL код. Тем не менее, он должен выполнять правила COM-сервера (при этом необходимо зарегистрироваться и CLSID), но на самом деле это больше похоже на

Старая DLL не как COM-сервер в процессе.

 
Как построить COM-объект

COM-объект в процессе является DLL, то есть, он имеет функцию DllMain (). Что еще более важно, выход COM объект

Четыре полных-перекрестки, эти функции выполняются любым контейнером, который работает с объектом в процессе. Они есть:

DllGetClassObject()

DllCanUnloadNow()

DllRegisterServer()

DllUnregisterServer()

Последние две автоматические регистрации и выхода из системы функций. Если вы обещаете вручную зарегистрироваться и войти, вы можете сделать эти две функции. Наш COM объект теперь

Эти две функции вычитаются в это время только два полной выходной функции: DllGetClassObject () и DllCanUnloadNow ().

 
Функция DllGetClassObject ()

Ни один клиент любого объекта СОМ должен сначала загрузить библиотеку, содержащую этот COM-объект, а затем функции через DllGetClassObject ()

Количество интерфейсных указателей:

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv);

В центре внимания вызвать эту функцию сразу после загрузки объекта класса. Другими словами, этот код всегда может быть реализовано. Что еще более важно, это

Это выполняется в соответствующем пространстве корпуса.

 
Встречайте ожидания клиентов

Как правило, модуль загруженного объекта вызывает DllGetClassObject (), просит IClassFactory интерфейс, наши клиенты —

В соответствии с действующим случае детектор — ожидает указатель интерфейса, возвращенный функции DllGetClassObject (). Потому что мы не поняли это

Интерфейс, как я могу иметь дело с этим ожиданием?

Для нас, класс явно объяснено не имеется, что необходимо только вернуть правильный код ошибки:

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)

{

return CLASS_E_CLASSNOTAVAILABLE;

}

Выше возможная реализация функции DllGetClassObject (), которая является ощущение того, что он не поддерживает определенные интерфейсы.

 
Используйте адрес оболочки пространства

Помимо возврата кода ошибки, эта функция также может сделать что-нибудь сделать с любым объектом находится на адресном пространстве оболочки.

Работа сделана. Когда DllGetClassObject () вызывается, мы уже в ассоциированном пространстве корпуса, так что это позволит мне.

Кнопка Подкласс «старт». После того, как потратить немного времени, чтобы обсудить функцию DllCanUnloadNow (), мы скоро это подтвердили.

 
DllCanUnloadNow () функция роли

Вызов функции DllCanUnloadNow () при загрузке объекта COM с помощью DllGetClassObject (), чтобы убедиться, что DLL может,

Удаление и выпущен безопасно. Детектор выполняет эту проверку периодически, хотя этот цикл может задержать десять секунд или десять минут. В главе 15

Мы обсудим это в расширении оболочки.

Если DllCanUnloadNow () возвращает S_OK, хозяин DLL будет удален. Если она всегда возвращает S_FALSE или DLL не имеет выхода

С этим именем, эта библиотека DLL освобождается только тогда, когда функция COUNInInitialize () выключена в главном приложении.

положил. Поскольку основное применение в настоящее время является зондом, библиотека DLL освобождаются некоторое время после вызова функции CoUninitialize ().

делать.

 
COM исходный код объекта

Далее это минимальный исходный код для этого «фальшивых» COM-объект, используемый, чтобы совмещать функции shloadInproc (), а в качестве

Семена подпрограмм, которые будут постепенно расти в «начиная» кнопки subclassics. Создать новую Win32 динамическую библиотеку в VC ++

Добавляет ‘Start’ (Выбрать ‘Simple DLL’ Options), добавьте следующий код в start.ccp:

#include «start.h»

HINSTANCE g_hInstance;

BOOL APIENTRY DllMain(HINSTANCE hInstance,

DWORD ul_reason_for_call,

LPVOID lpReserved)

{

g_hInstance = hModule;

return TRUE;

}

/*—————————————————————————*/

// DllGetClassObject

// Процесс COM-объекта в пределах

/*—————————————————————————*/

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)

{

// Выполняем некоторые операции

return CLASS_E_CLASSNOTAVAILABLE;

}

/*—————————————————————————*/

// DllCanUnloadNow

// Confirm Uninstall COM библиотека

/*—————————————————————————*/

STDAPI DllCanUnloadNow()

{

return S_OK;

}

Файл заголовка Start.h содержит CLSID в «поддельной» COM объекта, определенного выше:

#include <windows.h>

#include <windowsx.h>

#include <objbase.h>

#include <shlobj.h>

DEFINE_GUID(CLSID_NewStart, 0x20051998, 0x0020,0x0005,

0x19, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

Для вывода функции библиотеки, необходимо также определить файл Start.def:

LIBRARY START

EXPORTS

DllCanUnloadNow @1 PRIVATE

DllGetClassObject @2 PRIVATE

В конце этого раздела, вот код, который использует функцию shloadInproc () для загрузки COM в адресном пространстве детектора:

void DoGoInsideExplorer()

{

const CLSID clsid = {0x20051998,0x0020,0x0005,

{0x19,0x98,0x00,0x00,0x00,0x00,0x00,0x00}};

SHLoadInProc(clsid);

}

 
Регистрация COM объект

Есть два способа по существу зарегистрировать COM-объект: вставить код в функции DllRegisterServer (), или вручную зарегистрировать — самый

Легко использовать регистрационный сценарий. Теперь обратим внимание на эти два метода. Начнем с простейшего регистрации сценария в первую очередь.

Ниже приводится содержание REG-файл сценария, который автоматически обрабатывается в редакторе реестра. Он добавляет две регистрации CLSID в

CLSID узел и HKEY_CLASSES_ROOT сохранит имя исполняемого файла, который реализует COM.

REGEDIT4

[HKEY_CLASSES_ROOT/CLSID/{20051998-0020-0005-1998-000000000000}]

@= «Start Button»

[HKEY_CLASSES_ROOT/CLSID/{20051998-0020-0005-1998-000000000000}/InProcServer32]

@= «C://Chap07//Source//Start//start.dll»

«ThreadingModel» = «Apartment»

Конечно, обязательно, чтобы гарантировать путь, где регистрация является путь, где сам файл находится. Real, кнопка, которая должна быть добавлена ​​к CLSID должна быть упакована

Следующее имя CLSID прилагается следующим образом:

HKEY_CLASSES_ROOT

/CLSID

/{20051998-0020-0005-1998-000000000000}

Кроме того, мы также должны добавить еще одну кнопку под названием InProcServer32 под этим ключом, и его значение по умолчанию точки на имя фактического сервера. ценить

ThreadingModel указывает должн- потоковую модель. Для того, чтобы зарегистрировать этот сервер, необходимо дважды щелкнуть этот файл REG на зонде, или использовать его.

Редактор тома вводит его.

Формальный метод, чтобы написать это содержание все в функцию DllRegisterServer (), которая требует, чтобы мы использовали регистрацию Win32

Таблица API программирования. Мы объясним новую функцию высокого уровня набора с участием реестра в главе 10. На это

Мы можем использовать эти функции, однако, этот код будет использоваться только в 4.71 или выше. Следующий код использует традиционный Win32

API регистрации:

STDAPI DllRegisterServer()

{

TCHAR szSubKey[MAX_PATH] = {0};

TCHAR szCLSID[MAX_PATH] = {0};

TCHAR szModule[MAX_PATH] = {0};

HKEY hKey;

DWORD dwDisp;

// Установить CLSID

lstrcpy(szCLSID, __TEXT(«{20051998-0020-0005-1998-000000000000}»));

// получить имя модуля

GetModuleFileName(g_hInstance, szModule, MAX_PATH);

// HKCR: CLSID/{…}

wsprintf(szSubKey, __TEXT(«CLSID//%s»), szCLSID);

LRESULT lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, NULL,

REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp);

if(lResult == NOERROR)

{

TCHAR szData[MAX_PATH] = {0};

wsprintf(szData, __TEXT(«Start Button»), szModule);

lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ,

reinterpret_cast<LPBYTE>(szData), lstrlen(szData) + 1);

RegCloseKey(hKey);

}

// HKCR: CLSID/{…}/InProcServer32

wsprintf(szSubKey, __TEXT(«CLSID//%s//InProcServer32»), szCLSID);

lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, NULL,

REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp);

if(lResult == NOERROR)

{

lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ,

reinterpret_cast<LPBYTE>(szModule), lstrlen(szModule) + 1);

TCHAR szData[MAX_PATH] = {0};

lstrcpy(szData, __TEXT(«Apartment»));

lResult = RegSetValueEx(hKey, __TEXT(«ThreadingModel»), 0, REG_SZ,

reinterpret_cast<LPBYTE>(szData), lstrlen(szData) + 1);

RegCloseKey(hKey);

}

return S_OK;

}

COM объект выводит DllRegisterServer () в файле DEF, вы можете использовать системную утилиту regsvr32.exe для регистрации:

regsvr32.exe <full_server_name>

 
Выход COM объект

REG скрипт не позволяет выхода из системы настройки, так что единственный способ сделать это, чтобы удалить вручную с помощью редактора реестра. Если установлен

Сценарий среде Windows (WSH) может иметь другую программу, написать сценарий VB или функцию сценария Java, удалите с помощью объекта WSH реестра

Замечания и ценности. Поскольку язык сценариев является более гибким и универсальным, чем REG, этот метод станет популярным способом в будущем.

Говоря о языках сценариев, его значение в том, что COM-объекты, написанные с ATL может обеспечить регистрацию и выход из системы с RGS файлов. RGS сценарий не зарегистрирован

Версия расширения файла REG табличного редактора.

Вернуться к обсуждению о функции API, чтобы сделать объект COM самостоятельно, вы должны использовать следующую кодировку:

STDAPI DllUnregisterServer()

{

TCHAR szSubKey[MAX_PATH] = {0};

TCHAR szCLSID[MAX_PATH] = {0};

TCHAR szModule[MAX_PATH] = {0};

HKEY hKey;

DWORD dwDisp;

// Установить CLSID

lstrcpy(szCLSID, __TEXT(«{20051998-0020-0005-1998-000000000000}»));

// Открыть HKCR

LRESULT lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, «», 0, NULL,

REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp);

if(lResult == NOERROR)

{

wsprintf(szSubKey, __TEXT(«CLSID//%s//InProcServer32»), szCLSID);

RegDeleteKey(hKey, szSubKey);

wsprintf(szSubKey, __TEXT(«CLSID//%s»), szCLSID);

RegDeleteKey(hKey, szSubKey);

RegCloseKey(hKey);

}

return S_OK;

}

В этой функции мы открываем HKEY_CLASSES_ROOT и удалять ключи. RegdeleteKey () в Windows9x и Windows,

Это немного отличается от NT. Первое позволяет ключ содержать суб-ключ, это рекурсивное удаление не поддерживается в NT, если данная кнопка недоступна, эта функция

неудача. Обратите внимание, что «пустой» означает, что нет подключи, а не значение, он выразил. Так как приведенный выше код сначала удаляет внутреннюю часть внутреннего ключа,

Может работать на платформе.

Выход DllUnregisterServer () COM-объекты могут быть зарегистрированы путем полезности системы regsvr32.exe:

regsvr32.exe /u <full_server_name>

 
Новая кнопка запуска

Для того, чтобы проиллюстрировать способность ShLoadInProc (), мы даем код, чтобы расширить функции DllGetClassObject (), созданный

Кнопка Новый «старт», который имеет различные изображения и меню. Мы достигнем этой цели с помощью следующих шагов:

Получить кнопку «Пуск» ручки

Заменить его изображение

Подкласс окно кнопки, изменение меню и курсор

Создание и отображение пользовательского меню

Затем, вы можете контролировать клавишу «Windows» и комбинацию «Ctrl + Esc». Вы можете также ограничить их, пусть отображать стандарт «открытым

Меню», или соединить их с новым меню пользователя. Желаемые результаты приведены ниже:

                      
Первое, что является основной функцией, которая встроена в DllGetClassObject (). Это первый шаг в входе в оболочку неизвестной области.

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)

{

InstallHandler();

return CLASS_E_CLASSNOTAVAILABLE;

}

/*——————————————————-*/

// InstallHandler

// Заменить стартовое меню и установите крюк

/*——————————————————-*/

void InstallHandler()

{

if(g_bInstalled)

{

int irc = MessageBox(HWND_DESKTOP,

__TEXT(«The extension is installed. Would you like to uninstall?»),

__TEXT(«Start»), MB_ICONQUESTION | MB_YESNO | MB_SETFOREGROUND);

if(irc == IDYES)

UninstallHandler();

return;

}

/ / Помните, если установлен процессор

g_bInstalled = TRUE;

// Установить новый кнопку «старт»

SetNewStartButton(TRUE);

}

Когда вы закончите, вы должны восстановить стандартное поведение, вызов деинсталлировать свою функцию:

void UninstallHandler()

{

// Восстановление стандартных настроек

SetNewStartButton(FALSE);

// процессор деинсталляцию

g_bInstalled = FALSE;

}

В детекторе вызывает DllCanUnloadNow (), чтобы выяснить, является ли наша библиотека может быть удалена, существование этого процессора теперь станет ключевым

фактор. В этом разделе, мы должны сделать это, чтобы убедиться, что нет никакой угрозы во время установки этого процессора.

STDAPI DllCanUnloadNow()

{

return (g_bInstalled ? S_FALSE : S_OK);

}

После предоставления этой функции, теперь мы можем работать процессор установки и удаления кнопки «Пуск», давайте посмотрим

Несколько шагов, необходимых быть поставлена ​​задача.

 
Получить Handle кнопки

Потому что мы превращаем хорошо известный компонент интерфейса ОС Windows, результат очевиден, но на самом деле мы делаем

Это самая трудная часть работы в адресном пространстве оболочки. Остальные работы просто применяются к некоторым объектам оболочки для технологии программирования Win32.

да. Обратите внимание, что это действительно важно, что наш минимальный объект COM (в Start.dll) работает в той же среде, в качестве детектора.

Кнопка «Пуск» нормальное окно «Button», так же, как оно отображается в Spy ++:

                                      
 
Использование Spy ++ Search Tool Найти эту кнопку в большом количестве оконных стеки относительно легко: Просто перетащите поиск в нужное окно, оно будет

Выбирается окно списка. Этот инструмент поиска находится под «Поиск | Найти окно …» меню.

Если вы хотите запрограммировать Ручка подокна восстановления, вы должны использовать FindWindowEx (), а не FindWindow (),

В да, бывший можно указать корневое окно, начиная с поиска. В нашем случае, кнопка «Пуск» является суб-окна на панели задач в системе

Это уникальное окно класса окна Shell_TrayWnd.

hwndTray = FindWindowEx(NULL, NULL, «Shell_TrayWnd», NULL);

hwndStart = FindWindowEx(hwndTray, NULL, «Button», NULL);

Выше часть первого возобновляет Handle окна таблицы задач, а затем восстановить первый суб-окно класса «Button».

Вне зависимости от их внешнего вида, другая «кнопка» на панели задач вы видели не кнопка. На самом деле, они не являются окна

Порт — Они просто контроль TAB кнопки класса.

 
Замена изображения

После наблюдения SPY ++ скриншота выше, вы заметите, «начать» кнопку без названия, то есть, «начать» слово (

Не-английская версия Windows, локализована) является растровым изображением. Однако, в shell32.dll, или explorer.exe, или любой

Вы не можете найти след этого образа в других модулях системы. Это изображение нанизывая на объединенном мечения Windows, и один ресурс

Учредил. Оба хранятся в Explorer.exe.

                                        
Идентификатор диаграммы тегов Windows, является 143, и «запустить» строка в вертеле является 578.

                                                          
 
Комбинированное изображение создается путем копирования диаграммы тегов для Windows и рисования текста в ассоциации устройства памяти.

 
Обратное проектирование детекторных ресурсов

Если просмотреть зондовых ресурсы, вы увидите, что многие популярные изображения в различных диалогах (например, «Task Properties«Боб разговоры

Окно, показанное) динамически создана для экономии дискового пространства. На самом деле, только некоторые изображения элемента включены в файл Explorer.exe, и

Не результат результата финального дисплея.

Для того, чтобы просмотреть ресурсы приложения, следующий шаг предложения:

Создание резервной копии для просмотра файлов, это необходимо потому, что этот файл может быть в использовании.

Используйте VC ++, чтобы открыть его, не забудьте указать «ресурс» состояние в раскрывающемся окне, когда «открытый».

Под Windows 9x, IDE предупредит и не может обновлять ресурсы. Будь то.

После отображения дерева ресурсов, легко сохранить их в разные файлы. Просто щелкните правой кнопкой мыши на ресурсы, которые вы хотите сохранить, и выберите «Output …

». Эта операция доступна только для ресурсов, отображенных на файлы, такие как Bitmap, графики и курсоры. И ресурсы клиентов, как AVI файлы.

Вы не можете сохранить шаблон диалогового окна для текстовых файлов.

 
Старт стиль кнопки

Кнопка «Пуск» имеет стиль BS_bitmap, то есть, его поверхность покрыта изображением, а не обычный текст (вы можете передать

Щелкните правой кнопкой мыши на окне в Spy ++ списке, затем выберите «Свойства … | Style», чтобы подтвердить это). Вызов следующей функции можно легко получить

Изображение Ручка:

g_hbmStart = reinterpret_cast<HBITMAP>(SendMessage(hwndStart,

BM_GETIMAGE, IMAGE_BITMAP, 0));

Заменить этот образ не сложно. Во-первых, чтобы загрузить новое изображение из ресурсов приложения с функцией LoadImage (), а затем

Функция SendMessage () позволяет отнести изображения для кнопки со стилем BS_bitmap. ссылочный параметр LPARAM возвращается на LoadImage ()

Ручка назад.

HBITMAP hbm = reinterpret_cast<HBITMAP>(LoadImage(g_hInstance,

MAKEINTRESOURCE(IDB_NEWSTART), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE));

SendMessage(hwndStart, BM_SETIMAGE,IMAGE_BITMAP, reinterpret_cast<LPARAM>(hbm));

Наши изображения используются в примере, их идентификатор IDB_NewStart, определенный в файле resource.h:

                                          
Для этого примера мы выбрали изображение, как изображение для того, чтобы упростить кодирование, мы поместить этот файл в ресурс модуля. это

Изображение имеет тот же размер (48×16) с помощью кнопки «Пуск», вы можете использовать любые изображения, которые вы любите, но рекомендуется, чтобы сохранить этот размер.

Просто изменили картинку, чтобы обновить сейчас, поверхность кнопки обновляется, кнопки необходимо повторно его площадь без клиентов, чтобы отразить наши

Вносить изменения. Мы можем заставить это действие, вызывая SetWindowPos () функции:

SetWindowPos(hwndStart, NULL, 0, 0, 0, 0,

SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME);

Для того, чтобы увидеть эффект работы, мы должны реализовать функцию setnewstartButton (), который помещает все сегменты кода, приведенные в передней.

,Следующее:

void SetNewStartButton(BOOL fNew)

{

// получить кнопку «Пуск» ручки

HWND hwndTray = FindWindowEx(NULL, NULL, «Shell_TrayWnd», NULL);

HWND hwndStart = FindWindowEx(hwndTray, NULL, «Button», NULL);

// изменить изображение

g_hbmStart = NewStartBitmap(hwndStart, fNew);

}

Handle, который получил кнопку является ничтожной работой, и работа, используя способ, чтобы заменить его изображение требует немного логики. Это

Почему мы отделили этот код от причины вызова функции в newstartBitMap ():

HBITMAP NewStartBitmap(HWND hwndStart, BOOL fNew)

{

if(!fNew)

{

if(g_hbmStart)

SendMessage(hwndStart, BM_SETIMAGE, IMAGE_BITMAP,

reinterpret_cast<LPARAM>(g_hbmStart));

// изменение ответа Refresh кнопки

SetWindowPos(hwndStart, NULL, 0, 0, 0, 0,

SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME);

return NULL;

}

/ / Сохранить текущее изображение

g_hbmStart = reinterpret_cast<HBITMAP>(SendMessage(hwndStart,

BM_GETIMAGE, IMAGE_BITMAP, 0));

// Как создать новый образ

HBITMAP hbm = reinterpret_cast<HBITMAP>(LoadImage(g_hInstance,

MAKEINTRESOURCE(IDB_NEWSTART), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE));

SendMessage(hwndStart, BM_SETIMAGE, IMAGE_BITMAP,

reinterpret_cast<LPARAM>(hbm));

// кнопка Обновить, чтобы насладиться изменения

SetWindowPos(hwndStart, NULL, 0, 0, 0, 0,

SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME);

return g_hbmStart;

}

Теперь есть полный код, который необходимо создать рабочий DLL. После регистрации, вы можете использовать функцию, как DogoIndeExplorer ().

Вызов shLoadInProc (), и разрешить этот поддельный объект COM ввести адресное пространство детектора.

 
окно Подкласс

Изменение «Start» изображение кнопки является основным результатом, но мы также можем добиться большего. Следующая цель изменить это

Поведение кнопки, а именно:

Установите курсор в виде руки вместо обычного курсора

Удалить соответствующее меню

Индивидуальные окна этикетки инструмент

Самое интересное заключается в создании другого меню на кнопку «Пуск».

 
Рука курсор

Так как мы сделали кнопку «пуск», как цепи, курсор над ним также следует изменить в указательный палец.

Форма, как правило, нравится в HTML-цепи. Используйте ту же технику, используемую на детекторе, чтобы удалить это из ресурсов IE

Курсор, называется IDC_Hand (в наших ресурсах приложения).

Каждый раз, когда Windows, необходимо отобразить курсор в окно, он посылает сообщение WM_SETCURSOR. Если приложение не обрабатывает его, Windows является

Этот класс устанавливает предопределенный курсор. Определить курсор класса при использовании RegisterClass () или RegisterClassEx () класса регистрации — это

Является ли поле структуры WNDCLASS (или WNDCLASSEX). Для управления системой (например, кнопки), предопределенные курсоры являются стандартными векторы, только

Одним из исключений является контроль редактирования.

Если мы хотим, чтобы начать обработку сообщений, отправляемых системой на кнопку «Пуск», теперь нам нужно subcatenation. Добавлять

Код начали устанавливать процесс, называемый newStartProc () в коде setnewstartButton ():

void SetNewStartButton(BOOL fNew)

{

// получить кнопку «Пуск» ручки

HWND hwndTray = FindWindowEx(NULL, NULL, «Shell_TrayWnd», NULL);

HWND hwndStart = FindWindowEx(hwndTray, NULL, «Button», NULL);

// изменить изображение

g_hbmStart = NewStartBitmap(hwndStart, fNew);

// кнопка Подкласс

if(fNew)

{

if(!g_bSubclassed)

{

g_pfnStartProc = SubclassWindow(hwndStart, NewStartProc);

g_bSubclassed = TRUE;

}

}else{

if(g_pfnStartProc != NULL)

SubclassWindow(hwndStart, g_pfnStartProc);

g_bSubclassed = FALSE;

}

}

Когда указатель мыши находится в этом окне, чтобы отобразить другой курсор, мы должны инструкции отвечать на сообщения WM_SETCURSOR, который производится нами.

Подкласс «старт» Когда принимается окно, сообщение, полученное в окне:

LRESULT CALLBACK NewStartProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

switch(uMsg)

{

case WM_SETCURSOR:

SetCursor(LoadCursor(g_hInstance, MAKEINTRESOURCE(IDC_HAND)));

return 0;

}

return CallWindowProc(g_pfnStartProc, hwnd, uMsg, wParam, lParam);

}

После обработки сообщения WM_SETCURSOR, крайне важно, из этого окна. Если да, Windows будет прекращена.

Выполнение кода сообщений по умолчанию и восстановить вектор курсор.

 
Удалить стандартное меню корреляции

Скрытая стандартное меню ассоциации проще, просто возвращает 0 при получении сообщения WM_CONTEXTMENU:

switch(uMsg)

{

case WM_SETCURSOR:

SetCursor(LoadCursor(g_hInstance, MAKEINTRESOURCE(IDC_HAND)));

return 0;

case WM_CONTEXTMENU:

/ / Создать собственное всплывающее меню здесь

return 0;

}

Конечно, никто не может остановить вас от отображения вашего собственного всплывающего меню в локальном дисплее меню, вы должны использовать вас в верхнем коде.

Код заменяет комментарий строку.

 
Индивидуальные этикетки инструмента

Другая форма, которая может быть настроена в тег инструмента — может рассмотреть вопрос об изменении сообщения по умолчанию «Нажмите здесь, чтобы начать. Несмотря на программы Win32

Вы никогда не использовать метку инструмента, вы также должны знать, что это трудолюбивая гайка. Есть ли простой способ почувствовать, какой из них в настоящее время?

Ярлык инструмента активен, и даже если уведомление TTN_SHOW захватывается (когда окно закладки инструмента на дисплее, уведомляющее сообщение отправлено),

Вы не можете отменить эту метку.

Ярлык инструмента кнопки «Пуск» происходят от обработки коды кнопки. При запуске полоса задачи устанавливает панель инструментов

Войти окно и установить некоторые инструменты. Таким образом, чтобы получить Handle этого окна, чтобы отобразить инструмент тег кнопки «Пуск», один может

Метод заключается в использовании EnumThreadWindows () функция пересекала все окна, созданные в текущем потоке. Состояние только окна тега один инструмент

: Только один. Следующий код дает инструменты для того, как получить окно тегов инструмента и на соответствующую кнопку «Пуск». (Инструмент здесь метка

Область, которая появляется — в том случае, когда кнопка «Пуск» является областью клиента).

void RemoveTooltip(HWND hwndStart)

{

EnumThreadWindows(GetCurrentThreadId(), EnumThreadWndProc,

reinterpret_cast<LPARAM>(hwndStart));

}

// Эта нить только устанавливает окно инструмента тегов, все окна, принадлежащие к этой теме перечислены найти этот инструмент тег.

// Функция обратного вызова получает все окна ручки, созданную этот поток. LPARAM является ручкой кнопки (HWndStart) Start.

BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM lParam)

{

TCHAR szClass[MAX_PATH] = {0};

GetClassName(hwnd, szClass, MAX_PATH);

if(0 == lstrcmpi(szClass, TOOLTIPS_CLASS))

{

/ / Найти окно метки инструмента и попытаться найти инструменты

int iNumOfTools = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);

for(int i = 0 ; i < iNumOfTools ; i++)

{

/ / Получить информацию об этом инструменте я-я

TOOLINFO ti;

ti.cbSize = sizeof(TOOLINFO);

SendMessage(hwnd, TTM_ENUMTOOLS, i, reinterpret_cast<LPARAM>(&ti));

if(ti.uId == static_cast<UINT>(lParam))

{

// Найти инструмент кнопки «Пуск».

ti.lpszText = __TEXT(«Buy this book!»);

SendMessage(hwnd, TTM_UPDATETIPTEXT, 0,

reinterpret_cast<LPARAM>(&ti));

}

}

return FALSE;

}

return TRUE;

}

После получения хэндло окно Tag Tool, мы используем интерфейс инструмента тегов для перечисления каждого инструмента. Инструмент представляет собой правило площадь,

Когда мышь парит, он вызывает подсказку, которая описывается структурой TOOLINFO. Во время инструмента перечисления, «Пуск» кнопка инструмента

Быть идентифицированы путем сравнения UID поле TOOLINFO с помощью кнопки «Пуск». После этого вы можете удалить его, то лучше сохранить, текст может быть подключен

Сообщение TTM_UPDATETIPText заменяется.

Этот код имеет два ограничения. Во-первых, текущий поток только устанавливает окно инструмента тег, во-вторых, связанные с «начала

Инструмент кнопки»имеет флаг TTF_IDishWnd, то есть инструмент, связанный с областью клиента окна, а не общий прямоугольник. также,

Членом UID структуры TOOLINFO содержит HWND из соответствующего окна. Это не странно, из-за окно определяется тег инструмента

При назначении флага TTF_IDISHWND является общей привычкой. Это значительно упрощает нашу работу. Потому что ты можешь

Легко для того чтобы определить (или даже удалить) инструмент для кнопки «Пуск». Tooltips_class это некоторые элементы управления из General Tools — Инструменты Показать теги

— имя окна класса предусмотрено.

Если вы хотите изменить текст тега инструмента, помните, что это изменение не связанно с запущенным модулем. Даже установка его модуля

Уже удалили, она все еще продолжается. Единственный способ восстановить старую этикетку, чтобы изменить его обратно к предыдущим настройкам.

 
Новое меню

Когда пользователь нажимает на эту кнопку, отображается меню по умолчанию «старт». Точнее, когда кнопка получает BM_SETSTATE

Когда сообщение установлено, WPARAM установлен в значение TRUE, то отображается меню. BM_SETSTATE это кнопка патентованное сообщение, используется для запроса на кнопку, чтобы сделать «Нажмите»

Или режим «освобождение». Значение WPARAM это описание кнопки Правда требует, чтобы FALSE отпущена. Если ваша цель просто скрыта

Стандартное меню, просто обработать сообщение BM_SETSTATE и возвращать 0.

Когда нажмите кнопку Windows, или нажмите CTRL + ESC, это может вызвать сообщение BM_SETSTATE для отправки на эту кнопку. Лечить это сообщение

Операция, вы можете также захватить комбинацию этих клавиш.

 
Правильное поведение

Предположим, у вас есть меню для отображения. Вы можете попробовать его с сообщением WM_LBUTTONDOWN:

TrackPopupMenu(hmnuPopup, uFlags, ix, iy, 0, hwnd, NULL);

Если указаны правильные координаты, меню будет отображаться в месте, рядом с кнопкой. Однако эта кнопка не будет иметь возможность использовать режим «Пресс».

Итак, вам нужно отправить сообщение BM_SETSTATE в «Press» и эта кнопка «Release». Converse, отправить саму кнопку

Это сообщение будет прекращено и обрабатывается начальным процесс окна, которое мы заменили. В результате, стандарт «начать»

один.

Эта проблема в том, что кнопка «Пуск» является суб-окна на панели задач. Каждый раз, когда вы нажимаете (или отправить сообщение BM_SETSTATATE),

И Windows автоматически информирует родительское окно это событие. Кнопка сообщение BN_CLICKED. Задача по обработке сообщений BN_CLICKED

В статье (не кнопка) показывает стандартное меню.

Мы хотим предоставить меню, но вы должны сделать «Пресс» метод. Как мы получаем такое поведение? нам нужно

Функция независимого внешнего вида кнопки участка, который находится в процессе начальных кнопок — процесс рисования кнопок в обычном порядке, не делать какой-либо

Другие процессы или процессы, которые вызывают какие-либо другие вещи. Адрес этого процесса может быть восстановлен в getClassInfo () WNDCLASS узел

Найдено в конструкции:

switch(uMsg)

{

case WM_SETCURSOR:

SetCursor(LoadCursor(g_hInstance, MAKEINTRESOURCE(IDC_HAND)));

return 0;

case WM_CONTEXTMENU:

return 0;

case WM_LBUTTONDOWN:

{

WNDCLASS wc;

GetClassInfo(NULL, «Button», &wc);

CallWindowProc(wc.lpfnWndProc, hwnd, BM_SETSTATE, TRUE, 0);

/ / Call TrackPopupMenu здесь ()

CallWindowProc(wc.lpfnWndProc, hwnd, BM_SETSTATE, FALSE, 0);

return 0;

}

}

Приведенный выше код гарантирует, что наша кнопка «Пуск» имеет правильное поведение и отображает прижимания, когда появится меню. Эта строка кода:

CallWindowProc(wc.lpfnWndProc, hwnd, BM_SETSTATE, TRUE, 0);

Теперь, как внешняя функция, ручка кнопки «Пуск» используется в качестве параметра.

Это может быть странно, есть еще один способ сделать это: подкласс задачи окна баров и объяснение BN_CLICKED сообщения. Тем не менее, я больше

Как этот метод потому, что он уменьшает количество subclassics.

 
Как захватить Ctrl-Esc и Windows, ключи

Нажмите кнопку Windows, чтобы отправить сообщение BM_SETSTATE (устанавливается истина) к кнопке «Пуск» клавиш CTRL-ESC и,

Он отображает меню «Пуск». Кнопка Подкласс «старт», мы можем решить проигнорировать это событие:

case BM_SETSTATE:

return 0;

Или выбрать для отображения нашего собственного альтернативного меню:

case BM_SETSTATE:

case WM_LBUTTONDOWN:

{



}

 
Создание самостоятельного рисования меню

TrackPopupMenu () является хорошим способом для отображения меню в определенном месте экрана, но «начать» имеет два дополнительных свойства.

Это делает его отличным от обычного меню. Во-первых, это само рисование меню, второй, он должен отображаться в строгом определении — близко к панели задач

И расположение кнопки «Пуск». Если полоса задачи пришвартована в нижней части экрана, меню должно отображаться на кнопке «Пуск», если он

В верхней части, меню должно быть ниже его. Таким образом, для того, чтобы определить правильные координаты меню, мы в первую очередь необходимо знать расположение панели задач системы.

 
Определить положение экрана меню

TrackPopupMenu () должен представлять позицию с координатами (х, у) на экране. Интересно, что вы можете сказать функции, как объяснить каждый

Координатный, как организовать это меню. Например, если указан флаг TPM_BOTTOMALIGN, то у координаты находится в нижней части меню, если

Набор tpm_rightalign, Х координата в правой части меню.

Положение всплывающего меню зависит от этих трех информационных фильмов: X- и Y-координату, и кучу знаков. Мы упаковываем его в имени

В структуре STARTMENUPOS, и определить вспомогательную функцию для проверки расположения панели задач и равномерно заполнить эту структуру:

struct STARTMENUPOS

{

int ix;

int iy;

UINT uFlags;

};

typedef STARTMENUPOS* LPSTARTMENUPOS;

void GetStartMenuPosition(LPSTARTMENUPOS lpsmp)

{

/ / Получить край и положение панели задач

APPBARDATA abd;

abd.cbSize = sizeof(APPBARDATA);

SHAppBarMessage(ABM_GETTASKBARPOS, &abd);

switch(abd.uEdge)

{

case ABE_BOTTOM:

lpsmp->ix = 0;

lpsmp->iy = abd.rc.top;

lpsmp->uFlags = TPM_LEFTALIGN | TPM_BOTTOMALIGN;

break;

case ABE_TOP:

lpsmp->ix = 0;

lpsmp->iy = abd.rc.bottom;

lpsmp->uFlags = TPM_LEFTALIGN | TPM_TOPALIGN;

break;

case ABE_LEFT:

lpsmp->ix = abd.rc.right;

lpsmp->iy = 0;

lpsmp->uFlags = TPM_LEFTALIGN | TPM_TOPALIGN;

break;

case ABE_RIGHT:

lpsmp->ix = abd.rc.left;

lpsmp->iy = 0;

lpsmp->uFlags = TPM_RIGHTALIGN | TPM_TOPALIGN;

break;

}

}

ShappbarMessage () является функцией API, определенная в shellapi.h, возвращает края и позицию панели задач системы. Она также может быть доступна

Другие услуги (в главе 9). Функция GetStartMenuPosition () позволяет начать в правильном положении относительной панели задач

‘меню. Это всплывающее меню дисплея выглядит следующим образом:

case WM_LBUTTONDOWN:

{

WNDCLASS wc;

GetClassInfo(NULL, __TEXT(«Button»), &wc);

CallWindowProc(wc.lpfnWndProc, hwnd, BM_SETSTATE, TRUE, 0);

STARTMENUPOS smp;

GetStartMenuPosition(&smp);

HMENU hmenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MENU));

HMENU hmnuPopup = GetSubMenu(hmenu, 0);

TrackPopupMenu(hmnuPopup, smp.uFlags, smp.ix, smp.iy, 0, hwnd, NULL);

CallWindowProc(wc.lpfnWndProc, hwnd, BM_SETSTATE, FALSE, 0);

return 0;

}

Каждый пункт меню мы выбрали посылает сообщение WM_COMMAND к окну HWND, который ничем не отличается от самой кнопки. Таким образом, наш ребенок

Процесс классификации также обрабатывает выбор пользователя. Через некоторое время, дальнейшее объяснение.

 
Загрузить новое меню

Давайте построим очень простое предопределенное меню для замены стандартного меню, назовите его Idr_Menu. Вы можете передать себя

После загрузки функция TrackPopupMenu () и отображается, но вы скоро поймете, что это совсем не удалась. На самом деле, мы получаем

Традиционное меню текста в стиле:

                                
Вместо это меню Windows «Пуск» является самостоятельным рисунком меню, каждый из которых обращаются пользовательскими процедурами. тем не мение

К сожалению, в VC ++ редактор ресурсов не позволяет построить автономный рисунок меню в «визуальный», так что вы должны запрограммировать все.

Если вы хотите нарисовать меню, уже существует (если он хранится в ресурсах модуля), первый шаг должен пройти

Элемент, назначить специальную атрибут MF_OWNERDRAW для каждого пункта меню. Этот флаг определяет свой контент, который будет нарисован пользовательским процессом.

Отказ Ниже приведен сегмент кода, получить всплывающее меню и установить свой собственный стиль для каждого элемента:

// Разрешить максимальный размер имени проекта

const int ITEMSIZE = 100;

struct MENUSTRUCT

{

TCHAR szText[ITEMSIZE];

int iItemID;

TCHAR szFile[MAX_PATH];

};

typedef MENUSTRUCT* LPMENUSTRUCT;

void MakePopupOwnerDraw(HWND hwnd, HMENU hmnuPopup)

{

// Круговая вывод обхода бомбы

for(int i = 0 ; i < GetMenuItemCount(hmnuPopup) ; i++)

{

/ / Забронировать некоторые данные для самостоятельной окрашенной функции

LPMENUSTRUCT lpms = GlobalAllocPtr(GHND, sizeof(MENUSTRUCT));

int iItemID = static_cast<int>(GetMenuItemID(hmnuPopup, i));

GetMenuString(hmnuPopup, iItemID, lpms->szText, ITEMSIZE, MF_BYCOMMAND);

lpms->iItemID = iItemID;

UINT uiState = GetMenuState(hmnuPopup, iItemID, MF_BYCOMMAND);

ModifyMenu(hmnuPopup, iItemID, uiState | MF_BYCOMMAND | MF_OWNERDRAW,

iItemID, reinterpret_cast<LPCTSTR>(lpms));

}

}

При одновременном понимании значения элемента меню вы можете захотете сохранить некоторую информацию, такую ​​как строка дисплея, в течение которого вы можете

Менструктура хранит их, указатель на эту структуру передается функции в качестве последнего параметра функции ModifyMenu (),

Резервуар также передается функции фактического меню чертежа. Эта память должна быть выпущена по аналогичной процедуре, она должна быть завершена

Одиночная операция называется.

 
Самостоящая разделительная линия

Если мы действительно намереваемся генерировать меню, аналогичное меню «Пуск» Windows STANDAL, вам также необходимо создать самостоятельное разделение

Нить. Поскольку меню «Пуск» дает непрерывный вертикальные ленты вдоль края, элемент и линия разделения эффективно снижаются.

Горизонтальная область. По умолчанию линия разделения нарисована в виде вставленной проволоки при работе, т. Е. Нам нужно нарисовать разделительную линию в качестве элемента.

 
Пункт меню динамического сбора

Для этого примера мы решили загрузить новые меню из ресурсов проекта. «Пуск» меню составляет полторы

Меню, следовательно, элементы меню могут быть частично определены частично. Если вы установили специальную папку «Пуск меню» (см. Главу 6)

Ярлыки, вы можете представить новые элементы, чтобы сделать его в меню. Наш процессор также определяет аналогичные механизмы.

Создайте каталог (жесткий код C: / MyStartmenu), заполните его ярлыком в меню. В дополнение к этим динамическим предметам, я

Тогда «начать» меню всегда содержат «фиксированную» команду для восстановления предыдущих настроек и начальных меню. Нажмите ярлык, чтобы позвонить

Стандартный файл, нажмите на фиксированный элемент, чтобы привести к удалению процессора.

Следующая функция GetMenuhandle () устанавливает меню, отображаемое новым «Пуск». Он охватил каталог C: / MyStartmenu

Поиск файлов lnk, parsed и добавлять связанные значки и имена в меню.

HMENU GetMenuHandle(LPTSTR szPath)

{

LPMENUSTRUCT lpms;

int iItemID = 1;

// Эти полное переменное меню, нарисованное сейчас

g_balreadydrawn = false; // не начнется

g_bfirsttime = true; // первый доступ

// установить пустое меню

HMENU hmenu = CreatePopupMenu();

// Строка фильтра * .lnk

TCHAR szDir[MAX_PATH] = {0};

lstrcpy(szDir, szPath);

if(szDir[lstrlen(szDir) — 1] != ‘//’)

lstrcat(szDir, __TEXT(«//»));

TCHAR szBuf[MAX_PATH] = {0};

wsprintf(szBuf, __TEXT(«%s*.lnk»), szDir);

// Поиск .lnk.

WIN32_FIND_DATA wfd;

HANDLE h = FindFirstFile(szBuf, &wfd);

while(h != INVALID_HANDLE_VALUE)

{

// аналитический ярлык

SHORTCUTSTRUCT ss;

ZeroMemory(&ss, sizeof(SHORTCUTSTRUCT));

wsprintf(szBuf, __TEXT(«%s//%s»), szDir, wfd.cFileName);

SHResolveShortcut(szBuf, &ss);

// Создайте каждый элемент с идентификатором, описанием и целевым файлом

lpms = reinterpret_cast<LPMENUSTRUCT>(GlobalAllocPtr(GHND,

 sizeof(MENUSTRUCT)));

lpms->iItemID = iItemID;

if(!lstrlen(ss.pszDesc))

lstrcpy(lpms->szText, wfd.cFileName);

else

lstrcpy(lpms->szText, ss.pszDesc);

lstrcpy(lpms->szFile, ss.pszTarget);

// Добавить пункт меню

AppendMenu(hmenu, MF_OWNERDRAW, iItemID++, reinterpret_cast<LPTSTR>(lpms));

// следующий цикл

if(!FindNextFile(h, &wfd))

{

FindClose(h);

break;

}

}

// Добавить линию разделения и элемент «Восстановление»

AppendMenu(hmenu, MF_OWNERDRAW | MF_SEPARATOR, 0, NULL);

lpms = reinterpret_cast<LPMENUSTRUCT>(

GlobalAllocPtr(GHND, sizeof(MENUSTRUCT)));

lpms->iItemID = ID_FILE_EXIT;

lstrcpy(lpms->szText, __TEXT(«Restore Previous Settings»));

lstrcpy(lpms->szFile, «»);

AppendMenu(hmenu, MF_OWNERDRAW, ID_FILE_EXIT,reinterpret_cast<LPTSTR>(lpms));

return hmenu;

}

Эта функция представляет две полные логические переменные. G_BABLREADYDRANW используется для запоминания, если изображение было нарисовано в вертикальной полосе, потому что мы

Просто нужно рисовать один раз. G_BFIRSTTE используется для запоминания, если элемент нарисован в меню первым. Если эта переменная верна, меню

Верхний край прямоугольника сохраняется для определения высоты меню. Эти значения будут видны в следующих функциях.

Пункт меню опирается сверху вниз, и последний элемент определяется идентификатором в этой реализации — это фиксированный термин для удаления этого

процессор. Этот пункт существует в ресурсе DLL с значком 32×32 пикселей и идентификатор ID_FILE_EXIT. Другие пункты меню

Это получается в предыдущей главе предыдущей главы.

 
Установка Размер

Ресурс самоназыгрывателя, вызывает два сообщения, отправленные в их родительское окно, в этом случае эти новости прибудут на наш новый

«Начните» процесс кнопки, они являются:

WM_MEASUREITEM

WM_DRAWITEM

Первое сообщение используется для получения ширины и высоты одного элемента меню (агрегат пикселей), мы должны заполнить структуру в качестве сообщения. Второй

Спросите желаемую рисунку. Ниже приведена функция, которая обрабатывает сообщение WM_MEASUREITEM:

// Это абсолютные константы (агрегаты пикселей) определяют размер нарисованного

Const int defbitmapsize = 32; // 32 x 32 — это область, зарезервированная на изображение

Const int defdsize = 25; // ширина вертикальной полосы

Const int Defsepsize = 6; // Зарезервировано на высоту зоны раздела

Const Int Defbordersize = 2; // с зазором меню

void MeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)

{

SIZE size;

int iItemID = lpmis->itemID;

LPMENUSTRUCT lpms = reinterpret_cast<LPMENUSTRUCT>(lpmis->itemData);

// Рассчитать размер синдрома меню

HDC hdc = GetDC(hwnd);

GetTextExtentPoint32(hdc, lpms->szText, lstrlen(lpms->szText), &size);

ReleaseDC(hwnd, hdc);

// Установите ширину и высоту элемента

lpmis->itemWidth = DEFBITMAPSIZE + DEFBANDSIZE + size.cx;

// разделенный ID = 0

if(iItemID)

lpmis->itemHeight = DEFBITMAPSIZE;

else

lpmis->itemHeight = DEFSEPSIZE;

}

Переменная LPARAM из сообщения WM_MEASUREITEM указывает на структуру измерений, его относительно полей ItemHight и itemwidth

Требуется фактический размер требуемого элемента. В приведенном выше коде высота установлена ​​на 32 пикселя, ширина зависит от длины текста и является изображением (значок).

Пространство влево, и пропускная способность кромки меню (например, флаг Windows 98).

Обратите внимание, что постоянные постоянные постоянные здесь, поэтому появление меню «Пуск» остается прежним, независимо от того, какие настройки элемента есть.

Для получения дополнительной информации о структуре и механизме самопоглощения, используемого здесь, см. Официальную информацию о библиотеке MSDN.

 
Нарисуйте пункт меню

Всякий раз, когда Windows, необходимо отправить сообщение WM_DRAWITEM, когда данный пункт меню изображен. LPARAM переменная это указывает на сообщения

Структура DrawItemstruct, которая содержит всю информацию, необходимую для начертить операции. В принципе нам нужно окно меню, чтобы иметь вертикальный

С, то каждый элемент имеет значок и строку, область слева будет заполнена изображением.

Рисованные иконки и строка могут быть сделаны непосредственно с универсальной функцией API, такие как DrawIcon () и ExtTextOut (). При рисовании пунктов меню

Мы можем видеть только часть окна меню при работе. При рисовании изображения вдоль края окна меню, процесс немного отличается.

При выборе изменения, вызовите рисунок процесса один за пунктом, и мы должны найти способ, чтобы нарисовать только один образ, помните полную переменную

Как было обращено наше решение. Тем не менее, для нанесения изображений, есть больше работы, чтобы сделать.

Как нарисовать изображения и использовать BitBlt (), возможно, хороший способ. Windows, использует логику, сверху донизу, чтобы сделать свое собственное автономным окрашено меню

Отказ Поэтому, если она проходит (0, 0) в качестве начала назначения, изображение будет расположено в верхней части меню. Если вы посмотрите на Windows95, 98 и NT

В меню «Пуск», вы увидите, что изображение всегда расположены в нижней части меню, что делает проблему осложненной — правильность BitBlt ()

Что такое координатная? Х-координата равна 0, или абсолютное значение смещения относительного левого края, Y-координата должна быть подвергнута высоте окна меню.

Высота изображения дано. Так как BitBlt () обращаются от вершины до конца, то изображение будет расположено в нижней части. Для этого вопроса, есть основа

Простой способ одной высоты окна, мы знаем, что структура DrawItemStruct содержит прямоугольник текущего элемента, так что, если вы помните первый

Верхней части элемента и нижней части последнего элемента, высота окна неизбежно разница.

Таким образом, мы знаем высоту изображения и высоту окна. Это позволяет легко определить правильный Y координат становится функцией BitBlt ().

Легкий. Теперь дисплей должен быть таким же, как в меню стандартного «старт». Необходимый код приведен ниже:

void DrawItem(LPDRAWITEMSTRUCT lpdis)

{

TCHAR szItem[ITEMSIZE] = {0};

TCHAR szFile[MAX_PATH] = {0};

COLORREF crText, crBack;

HICON hIcon = NULL;

LPMENUSTRUCT lpms = reinterpret_cast<LPMENUSTRUCT>(lpdis->itemData);

int iItemID = lpdis->itemID;

int iTopEdge = 0;

/ / Save Item Text и Target File

if(lpms)

{

lstrcpy(szItem, lpms->szText);

lstrcpy(szFile, lpms->szFile);

}

// Управление операций рисования

if(lpdis->itemAction & (ODA_DRAWENTIRE | ODA_SELECT))

{

COLORREF clr;

RECT rtBand, rtBmp, rtText, rtItem, rt;

SIZE size;

// Определяет прямоугольник, который будет использоваться:

// lpdis-> rcitem является прямоугольником пункта меню

// RTBAND: вертикальный ленточнопильный область пунктов меню

// RTBMP: Область значков пунктов меню

// rtText: Раздел область текста пункта меню

CopyRect(&rt, &(lpdis->rcItem));

CopyRect(&rtBand, &rt);

rtBand.right = rtBand.left + DEFBANDSIZE;

CopyRect(&rtBmp, &rt);

rtBmp.left = rtBand.right + DEFBORDERSIZE;

rtBmp.right = rtBmp.left + DEFBITMAPSIZE;

CopyRect(&rtText, &rt);

rtText.left = rtBmp.right + 2 * DEFBORDERSIZE;

CopyRect(&rtItem, &rt);

rtItem.left += DEFBANDSIZE + DEFBORDERSIZE;

// Если это первый элемент, сохранить Y координат

if(g_bFirstTime)

{

iTopEdge = rtBand.top;

g_bFirstTime = FALSE;

}

// нарисовать прямоугольную и вертикальное изображение

if(!g_bAlreadyDrawn)

{

// Зона синий

clr = SetBkColor(lpdis->hDC, RGB(0, 0, 255));

ExtTextOut(lpdis->hDC, 0, 0,

ETO_CLIPPED | ETO_OPAQUE, &rtBand, NULL, 0, NULL);

SetBkColor(lpdis->hDC, clr);

// Если последний элемент, определить высоту меню, нагрузку и нарисовать изображение

if(iItemID == ID_FILE_EXIT)

{

int iMenuHeight = rtBand.bottom — iTopEdge;

HBITMAP hbm = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_LOGO));

DrawBitmap(lpdis->hDC, 0, iMenuHeight, hbm);

DeleteObject(hbm);

g_bAlreadyDrawn = TRUE;

}

}

// Выбор статуса не влияет на что-либо до сих пор.

// Рисуем иконки, текст и связанные с ними цвета фона

if(lpdis->itemState & ODS_SELECTED)

{

crText = SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));

crBack = SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));

}

/ / Очистить область правильно

ExtTextOut(lpdis->hDC, rtText.left, rtText.left,

ETO_CLIPPED | ETO_OPAQUE, &rtItem, NULL, 0, NULL);

// Получить значок, который можно сделать, если это последний элемент, поместите его из ресурса.

/ / В противном случае определить значок системы из целевого файла ярлыка.

if(iItemID == ID_FILE_EXIT)

hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(iItemID));

else{

SHFILEINFO sfi;

ZeroMemory(&sfi, sizeof(SHFILEINFO));

SHGetFileInfo(szFile, 0, &sfi, sizeof(SHFILEINFO), SHGFI_ICON);

hIcon = sfi.hIcon;

}

// Рисуем иконку (автоматическая прозрачность)

if(hIcon)

{

DrawIcon(lpdis->hDC, rtBmp.left, rtBmp.top, hIcon);

DestroyIcon(hIcon);

}

// Нарисовать текст (одна линия по вертикали)

if(!iItemID)

{

// отдельная строка

rt.top++;

rt.bottom = rt.top + DEFBORDERSIZE;

rt.left = rt.left + DEFBANDSIZE + DEFBORDERSIZE;

DrawEdge(lpdis->hDC, &rt, EDGE_ETCHED, BF_RECT);

}else{

/ / Возьмите размер текста соответствующего шрифта

GetTextExtentPoint32(lpdis->hDC, szItem, lstrlen(szItem), &size);

// Вертикальный дом

int iy = ((lpdis->rcItem.bottom — lpdis->rcItem.top) — size.cy) / 2;

iy = lpdis->rcItem.top + (iy >= 0 ? iy : 0);

rtText.top = iy;

DrawText(lpdis->hDC, szItem, lstrlen(szItem),

&rtText, DT_LEFT | DT_EXPANDTABS);

}

}

}

Над этим относительно прямой большой функции обрабатывается текстом и иконками, но рисует вертикальную карту тегов (это 25 пикселей в ширину)

Работа IDB_LOGO ресурсов остаются на следующую процедуру, DrawBitmap ():

void DrawBitmap(HDC hdc, int x, int iHeight, HBITMAP hbm)

{

/ / Эта функция вычисляет Y координат изображения на основе высоты зоны покрытия будут расположены вместе с дном.

BITMAP bm;

// Создание хранилища соответствующего устройства для выбора изображения

HDC hdcMem = CreateCompatibleDC(hdc);

HBITMAP hOldBm = static_cast<HBITMAP>(SelectObject(hdcMem, hbm));

// Получить информацию об изображении

GetObject(hbm, sizeof(BITMAP), &bm);

/ / Определение Y координат

int y = iHeight — bm.bmHeight;

y = (y < 0 ? 0 : y);

/ / Преобразовать изображение из памяти DC в меню DC

BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);

// Выпуск хранения DC

SelectObject(hdcMem, hOldBm);

DeleteDC(hdcMem);

}

Наконец исправить процесс окна кнопки категории, так что он может правильно построить наше меню клиента, и обработать WM_MEASUREITEM кольца и

WM_DRAWITEM сообщение:

switch(uMsg)

{

case WM_SETCURSOR:

SetCursor(LoadCursor(g_hInstance, MAKEINTRESOURCE(IDC_HANDY)));

return 0;

case WM_MEASUREITEM:

MeasureItem(HWND_DESKTOP, reinterpret_cast<LPMEASUREITEMSTRUCT>(lParam));

break;

case WM_DRAWITEM:

DrawItem(reinterpret_cast<LPDRAWITEMSTRUCT>(lParam));

break;

case WM_CONTEXTMENU:

return 0;

case BM_SETSTATE:

case WM_LBUTTONDOWN:

{

WNDCLASS wc;

GetClassInfo(NULL, «Button», &wc);

CallWindowProc(wc.lpfnWndProc, hwnd, BM_SETSTATE, TRUE, 0);

STARTMENUPOS smp;

GetStartMenuPosition(&smp);

HMENU hmnuPopup = GetMenuHandle(«c://myStartMenu»);

int iCmd = TrackPopupMenu(hmnuPopup,

smp.uFlags | TPM_RETURNCMD | TPM_NONOTIFY,

smp.ix, smp.iy, 0, hwnd, NULL);

// Ручка пользователь мыши

HandleResults(hmnuPopup, iCmd);

// Релиз памяти

DestroyMenu(hmnuPopup);

CallWindowProc(wc.lpfnWndProc, hwnd, BM_SETSTATE, FALSE, 0);

return 0;

}

}

 
Excuting заказ

Теперь меню завершено и работают, но его уникальный недостаток заключается в том, что нет никакого фактического действия в меню.

Из списка, вы можете увидеть ответ, handleresults () функция должна делать какую-то работу, проблема в том, где мы выбираем в меню?

Один предмет. Они просто применяя приказы или ярлыки для документов и программ?

Конечно, это в конечном счете, зависит от ваших потребностей. У нас есть выбор, чтобы прочитать содержимое и динамически запланированное меню в каталоге диска. (При добавлении

Добавлены ярлыки «Пуск» или «программы» меню, оболочка не делать этого. ). Как уже упоминалось ранее, предположим, что этот процессор выглядит

Сочетания объект File, затем разбор его, и прилагаются к меню, и, наконец, добавить разделительную линию и пункт стандартных «уходы».

Ярлык описывает текст пункта меню. Если ярлык не описывается (обычный случай), то используется имя файла.

Отказ При выборе этого пункта меню, процессорный модуль просто вызывает ярлык точку к.

void HandleResults(HMENU hmenu, int iCmd)

{

MENUITEMINFO mii;

LPMENUSTRUCT lpms;

if(iCmd <= 0)

return;

if(iCmd == ID_FILE_EXIT)

{

UninstallHandler();

return;

}

mii.cbSize = sizeof(MENUITEMINFO);

mii.fMask = MIIM_DATA;

GetMenuItemInfo(hmenu, iCmd, FALSE, &mii);

lpms = reinterpret_cast<LPMENUSTRUCT>(mii.dwItemData);

ShellExecute(NULL, __TEXT(«open»), lpms->szFile, NULL, NULL, SW_SHOW);

}

Если элемент является элемент «Восстановить предыдущую настройку», вызовите функцию выходов UninstallHandler (). Для любого другого выбора,

Путь к файлу исполнения извлекается в элемент данных, а затем вызвать функцию API ShellExecute () для выполнения этого файла. Наше меню клиента здесь

Это все завершено.

 
Браузер вспомогательный объект

ShloadInProc () является мостом, который позволяет вашей программе, чтобы вставить COM объект оболочки. Мы использовали наиболее

Малый COM объект демонстрирует эту операцию. Вы, конечно, можете использовать обычный объект COM, чтобы сделать это. Следует отметить, что для разработки этой функции

Вы не должны быть специальный COM программист. Просто спросите программу вы строите себя выразить как COM-объект: он должен иметь CLSID

, Вы должны быть зарегистрированы, а минимальная функция любого COM-сервера должен быть реализован. Не требуют для реализации каких-либо интерфейсов, а также не запрещает вам делать вам.

действовать. Вместо этого браузер вспомогательных объекты являются полным процессом в процессе COM-серверах, IE (и зондов) в создании новых экземпляров.

Этот объект загружен. Обратите внимание, что эти объекты всегда нужен экземпляр браузера, чтобы открыть таланты. Принцип такой деятельности будет

Краткое описание.

Использование shloadInproc (), это ваша программа, чтобы решить, когда войти в адресное пространство детектора, и должен ли он быть заблокирован

Введите адрес детектора пространства. Большая разница с помощью объекта поддержки браузера является то, что браузер (детектор или IE), автоматически загружается в конкретном реестре

Все модули зарегистрированы в районе.

Как у вас есть имена их названий, браузер-вспомогательный объект влияет только на определенную часть детектора — секции браузера позволяют просматривать

Часть файла и папки.

Теперь вы можете выбрать между двумя дополнительными способами — от вас, чтобы определить, каким образом два варианта лучше всего подходит для особых потребностей

Отказ Для того, чтобы помочь вам выбрать, мы рассмотрим преимущества и недостатки двух методов. Основное отличие состоит в:

Обратная совместимость

принцип деятельности

регистр

Структура СОМ-объект

Связь с основной программой

Использовать

Помните, что эти два варианта эффективных способов загрузки COM-объекты Shell пространства для хранения, мы также будем оценивать их в таких условиях. Из

Технической точки зрения, все это совершенно разные: shloadInProc () является функцией, а браузер вспомогательный объект является COM-объектом.

 
Обратная совместимость

SHLoadInProc () в оболочке после версии 4.00, и браузер вторичный объект относится к версии shell4.71 — они

Оба появились в IE4.0. Обе они работают во всех других, чем WindowsCE платформы Win32.

Помните, shell4.71 версии означает, что вы должны иметь IE4.0 или выше и активные рабочие столы. И два включены в Windows 98.

 
механизм деятельности

С этой точки зрения, оба метода очень разные. ShloadInProc () позволяет приложению нагрузки COM объектов в

Ассоциированное пространство оболочки. Вместо этого, браузер-вспомогательный объект является объектом регистрации, загружаются в память каждый раз, когда IE и детектор начать новый экземпляр каждый раз.

Вы не можете контролировать время загрузки браузера вспомогательного объекта.

Для того чтобы включить вспомогательный объект деятельности, необходимо открыть экземпляр зонда или браузера. Кроме того, пример вспомогательного объекта

Ассоциация с зондами или браузеров — После того, как связанный с ним экземпляр закрыт, вспомогательный объект удаляется.

 
регистр

ShloadInProc () может быть загружен с любым объектом правильной регистрации COM. Браузер Вспомогательные объекты должны быть зарегистрированы в указанном реестре

На пути, зонд или браузер может видеть (см объекта раздел регистрации помощи).

 
Структура СОМ-объект

Как показано выше, shloadInproc () может управлять и успешно загрузить любой COM-объект — даже подделка, нет

Существует объект, который реализует любой интерфейс. Браузер вспомогательный объект должен иметь четко определенный формат, который проверен в браузере (IE или детектор).

То есть для реализации правил интерфейса IObjectWithsite.

 
Связь с основной программой

Объект, который загружается через shloadInProc () не принимает указатели, которые указывают на интерфейс IUnknown оболочки. Это может быть преднамеренным

Ограничение праведности, так что если ваша цель только простой тип земли объект оболочки, вам не нужен этот указатель. Subcale, относится к нему допускается

Вы можете использовать обязательные средства для изменения и фильтровать любые методы объекта (например, кнопка «старт») поведение, является объектом «Я не знаю» вы

Способ перемещения.

С другой стороны, когда объект первичной среды имеет ссылку, разрешается связывать их через интерфейс общественного программирования, который является простым и безопасным

Полный сколько метод. Это также открывает новый путь для изучения функции, где обработка событий является наиболее полезной. Вспомогательная пара загружается в браузере

Как может принимать указатели, которые указывают на IWebBrowser2, и обрабатывать все браузеры, вызванные событиями. Эта связь представляет собой интерфейс IObjectWithSite

Поддерживается.

 
инструкции

ShloadInProc () может загрузить любой объект, в том числе преимуществ контрафактных объектов, принципе, вы можете также использовать

SHLoadInProc () загружает вспомогательный объект. К сожалению, это не позволяет вам общаться с оболочкой с интерфейсом IUnknown. Таким образом, в связи с этим

Браузер помощь объекты являются более распространенными, хотя это не может быть загружен. ShloadInProc () работает с зондом, а вспомогательный объект может

Работа как с IE и детекторов. Тем не менее, ShloadInProc () не требует примера детектора или IE.

У нас уже есть поддельный COM модуль, теперь пытаются зарегистрировать его в качестве вспомогательного объекта, он хорошо работает. В этом виде

В этом случае этот «минимальный» объект COM имеет тот же режим работы при загрузке с использованием SHLOADINPROC (): он всегда называется

Функция dllgetclassObject ().

 
Регистрировать вспомогательный объект

Вспомогательный объект браузера — это модуль COM, который должен быть зарегистрирован на пути ниже:

HKEY_LOCAL_MACHINE

/Software

/Microsoft

/Windows

/CurrentVersion

/Explorer

/Browser Helper Objects

Все CLSID, которые разрешены модулями, перечислены в клавише «Браузер Helper Objects». Детекторы (и то есть) загружают их один за другим. помнить

Новый экземпляр браузера также устанавливается при остановке папки «Recycle Bin» или «Принтер». То есть вспомогательный объект часто получается.

Используйте — по крайней мере, более частые, чем ожидалось (обратите внимание на окно диалога или режима …). Список этого вспомогательного объекта в реестре не кэшируется

Всегда оправляйте с диска, поэтому вы можете очистить модули, которые больше не полезны в точке — вам нужно только удалить реестр.

Соответствующая линия CLSID. К счастью, удаление объектов из этого под дереву не влияет на полный регистрационный статус этого сервера. Другие приложения еще

Найдите его с помощью клавиши CLSID, чтобы найти его с предыдущим методом.

 
IOBJECTWITHSITE интерфейс

Использование shloadinproc (), модуль можно загрузить в адресное пространство детектора, но у него нет комбинированного соединения. Другими словами

Он не может принять указатель в браузере IUKSNOWN, и он не может получить доступ к этой целевой модели. Доступные объекты через iObjectWithsite

Интерфейс ремонтируется.

Когда браузер загружает COM-сервер, перечисленный в реестре, он запрашивает интерфейс iObjectWithSite. Если вы найдете его,

Метод Setsite () передает указатель на интерфейс для браузера IUKSNOWN к этому модулю. IObjectWithsite включает в себя только дополнительные Iunknown

Два метода setsite () и getsite ().

HRESULT IObjectWithSite::SetSite(IUnknown* pUnkSite);

HRESULT IObjectWithSite::GetSite(REFIID riid, void** ppvSite);

Метод Setsite () вызывается браузером и как точка входа. Метод Getsite () работает с помощью QueryInterface () очень похожи. возвращение

Установленный на определенный указатель интерфейса, установленный Setsite (), установлен здесь.

 
Написать вспомогательный объект

Если вы планируете написать объект в браузере, ATL может предоставить важной справке. Как только ATL Com Master установлен

Framework, вы можете использовать Master Object, чтобы добавить новый объект и экспортировать его из iObjectWithSiteimpl. Вся остальная часть работы является использование

Вспомогательная логика пишет объекты метода Setsite ().

Чтобы проиллюстрировать это, мы перепишем инструменты, чтобы нажать на указанную клавишу, чтобы создать новую папку в качестве вспомогательного объекта. Пара браузера

Изображение более подходит для создания небольшой утилиты расширенного детектора, чем обычные расширения объектов Shell, поэтому объекты поддержки браузера, кажется, добавляют новые

Идеальный метод для ускорителя детектора. Нам больше не нужно применять код впрыска к пространству ассоциации детектора, противоположное заключается в том, что реализация должна быть установлена.

Комплект интерфейса iObjectWithsite. Следующее означает рассмотреть:

Найти ручку окна детектора

Почувствуйте крюк клавиатуры этого ускорителя

Наши предыдущие сценарии основаны на окне, созданном полный крючок. Когда процесс крюка чувствует себя определенным типом (Explorewclass), установлено

Он устанавливает частичный крючок на активности клавиатуры. Когда F12 нажимает, окно детектора принимает командное сообщение, чтобы вызвать новую папку. Взаимно

Обратный, вспомогательный объект загружен, когда окно детектора уже существует. Тем не менее, FindWindow () не является окном детектора поиска.

Indefic Function, потому что он возвращает верхнюю ручку окна указанного класса. Поэтому, если есть ряд зондов, мы будем работать одновременно.

Это наше окно, которое не может быть гарантировано, чтобы вернуться.

Если несколько зондов выполняются одновременно, каждый работает в собственном потоке. Для браузера помощи объекта, найти

Лучший метод для дескриптора окна детектора — перечислять окно, принадлежащее текущему потоку, код выглядит следующим образом:

EnumThreadWindows(GetCurrentThreadId(), WndEnumProc,

reinterpret_cast<LPARAM>(&m_hwndExplorer));

if(!IsWindow(m_hwndExplorer))

return E_FAIL;

Функция ENUMTHREADWINDOWS () — это функция API, которая перечисляет все окна, установленные указанным потоком. Каждое окно второе

Переменные доставляются в функцию обратного вызова. Ниже приведена обработка функции обратного вызова WNDENUMPROC ():

BOOL CALLBACK CNewFolder::WndEnumProc(HWND hwnd, LPARAM lParam)

{

TCHAR szClassName[MAX_PATH] = {0};

GetClassName(hwnd, szClassName, MAX_PATH);

if(!lstrcmpi(szClassName, __TEXT(«ExploreWClass»)))

{

HWND* phWnd = reinterpret_cast<HWND*>(lParam);

*phWnd = hwnd;

return FALSE;

}

return TRUE;

}

Третий параметр EnumThreadWindows () представляет собой 32-битное значение, которое может быть использовано вызывающей стороной для любых целей. Нам нужен вид

Получите окно детектора (если есть один) Ручка возвращаемого метода. Итак, используйте третий параметр, чтобы пройти указатель на переменную HWND.

Когда wndenumproc () находит окно с окном Explorewclass, он копирует эту ручку к указателю, затем пройти

Возвращает процесс перечисления ложных остановок.

Независимо от того, как появляется внешний вид, окно детектора фактически состоящее из всего стека окон. На следующем рисунке будет отображаться контурная концепция. Для получения подробной информации, пожалуйста, обратитесь к

Spy ++ точные окна классы и стили.

                      
 
Каждая клавиатура TAP отличается от окна ввода фокуса. Из-за установки локальных ключевых ключей мы можем ввести окно в нажатии на клавиш.

Традиционный проход рта обрабатывается.

 
Atl com объект

Давайте посмотрим на исходный код объекта вспомогательного браузера, где Master COM ATL создал каркас кода. Новый

Добавлен «простой объект» Newfolder. Newfolder.h Файлы заголовка следующие:

#ifndef __NEWFOLDER_H_

#define __NEWFOLDER_H_

#include «resource.h» // main symbols

///////////////////////////////////////////////////////////////////////////

// постоянный

const int NEWFOLDERMSG = 29281; // WM_COMMAND to send

const int NEWFOLDERKEY = VK_F12; // Key to detect

/////////////////////////////////////////////////////////////////////////////

// CNewFolder

class ATL_NO_VTABLE CNewFolder :

public CComObjectRootEx<CComSingleThreadModel>,

public CComCoClass<CNewFolder, &CLSID_NewFolder>,

public IObjectWithSiteImpl<CNewFolder>,

public IDispatchImpl<INewFolder, &IID_INewFolder, &LIBID_OBJFOLDERLib>

{

public:

CNewFolder()

{

m_bSubclassed = false;

}

~CNewFolder();

DECLARE_REGISTRY_RESOURCEID(IDR_NEWFOLDER)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CNewFolder)

COM_INTERFACE_ENTRY(INewFolder)

COM_INTERFACE_ENTRY(IDispatch)

COM_INTERFACE_ENTRY_IMPL(IObjectWithSite)

END_COM_MAP()

// INewFolder

public:

STDMETHOD(SubclassExplorer)(bool bSubclass);

// IObjectWithSite

public:

STDMETHOD(SetSite)(IUnknown* pUnkSite);

private:

bool m_bSubclassed;

HWND m_hwndExplorer;

// Перезвоните

static BOOL CALLBACK WndEnumProc(HWND, LPARAM);

static LRESULT CALLBACK KeyboardProc(int, WPARAM, LPARAM);

static LRESULT CALLBACK NewExplorerWndProc(HWND, UINT, WPARAM, LPARAM);

};

#endif //__NEWFOLDER_H_

Мы экспортируем класс NewFolder в стандартной реализации представленной АТЛ к интерфейсу IObjectWithsite. Единственное, что нужно сделать, это перегруженный

() Метод SetSite. Это ключевая функция вспомогательного объекта. Следующий код показывает, какой из них является окно датчика и устанавливает хук клавиатуры. Несмотря на то что

Этот пример не является строго обязательным, мы до сих пор subcatenate окна детектора. Таким образом, код дополнительно усиливается.

#include «stdafx.h»

#include «ObjFolder.h»

#include «NewFolder.h»

// Эти константы используются в статических членов класса

static WNDPROC g_pfnExplorerWndProc = NULL;

static HHOOK g_hHook = NULL;

static HWND g_hwndExplorer;

///////////////////////////////////////////////////////////////////////////

// CNewFolder

CNewFolder::~CNewFolder()

{

if(m_bSubclassed)

{

SubclassExplorer(false);

m_bSubclassed = false;

}

}

/*—————————————————————-*/

// SetSite

// вызывается с помощью детектора / IE, чтобы получить контакт

/*—————————————————————-*/

STDMETHODIMP CNewFolder::SetSite(IUnknown* pUnkSite)

{

HRESULT hr = SubclassExplorer(true);

if(SUCCEEDED(hr))

m_bSubclassed = true;

return S_OK;

}

/*—————————————————————-*/

// SubclassExplorer

// окно детектора Подкласс и установить хук клавиатуры

сын/*———————————————— —————— * /

STDMETHODIMP CNewFolder::SubclassExplorer(bool bSubclass)

{

// Получить HWND окна детектора

EnumThreadWindows(GetCurrentThreadId(), WndEnumProc,

reinterpret_cast<LPARAM>(&m_hwndExplorer));

if(!IsWindow(m_hwndExplorer))

return E_FAIL;

else

g_hwndExplorer = m_hwndExplorer;

// окно детектора Подкласс

if(bSubclass && !m_bSubclassed)

{

g_pfnExplorerWndProc = reinterpret_cast<WNDPROC>(SetWindowLong(

m_hwndExplorer, GWL_WNDPROC,

reinterpret_cast<LONG>(NewExplorerWndProc)));

// Установить хук клавиатуры чувствовать f12

g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc,

NULL, GetCurrentThreadId());

}

// окно детектора Non-ребенок

if(!bSubclass && m_bSubclassed)

{

SetWindowLong(m_hwndExplorer, GWL_WNDPROC,

reinterpret_cast<LONG>(g_pfnExplorerWndProc));

// удаляет крючки

UnhookWindowsHookEx(g_hHook);

}

return S_OK;

}

/*—————————————————————-*/

// WndEnumProc

// Перечислите статический член окна резьбы

/*—————————————————————-*/

// Вставьте код, указанный выше

/*—————————————————————-*/

// NewExplorerWndProc

// Заменить элемент статического процесса окна детектора

/*—————————————————————-*/

LRESULT CALLBACK CNewFolder::NewExplorerWndProc(HWND hwnd, UINT uMsg,

WPARAM wParam, LPARAM lParam)

{

// Ничего не делать, просто вызовите стандартный процесс

return CallWindowProc(g_pfnExplorerWndProc, hwnd, uMsg, wParam, lParam);

}

/*—————————————————————-*/

// KeyboardProc

// элемент Static ручки

/*—————————————————————-*/

LRESULT CALLBACK CNewFolder::KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)

{

/ / Типичный старт сегмент любого крюка

if(nCode < 0)

return CallNextHookEx(g_hHook, nCode, wParam, lParam);

// Кнопка Test только один раз (нажать и отпустить)

if((lParam & 0x80000000) || (lParam & 0x40000000))

return CallNextHookEx(g_hHook, nCode, wParam, lParam);

if(wParam == NEWFOLDERKEY)

PostMessage(g_hwndExplorer, WM_COMMAND, NEWFOLDERMSG, 0);

return CallNextHookEx(g_hHook, nCode, wParam, lParam);

}

 
Еще один делать при написании вторичного объекта, чтобы сделать его полностью зарегистрированы. Для того, чтобы правильно зарегистрировать браузерную помощь объект, вам нужно поместить следующее

Код добавляется в скрипт RGS:

HKLM

{

SOFTWARE

{

Microsoft

{

Windows

{

CurrentVersion

{

Explorer

{

‘Browser Helper Objects’

{

{B4F8DE53-65F4-11D2-BC00-B0FB05C10627}

}

}

}

}

}

}

}

Одна из проблем, с объектами помощи браузера является то, что они не являются полностью не объяснены, у них есть определенные указания информации. В библиотеке MSDN

Можно найти статью.

Это завершает этот проект код, теперь мы можем скомпилировать и подключить к этому проекту, зарегистрировать этот браузер, чтобы помочь объекту.

После установки объекта, будет клавиатура крючок в любом пробуждении детектора, и процесс F12 последовательно установлен в отображаемом каталоге.

Новая папка.

 
Вспомогательные объекты под Windows NT

Браузер вспомогательных объектов так же, как работает в Windows 9X в Windows. Процесс регистрации также согласуется с последующим

Дизайн логики. Существует только один, чтобы избежать дефектов: uncode. Под Windwosnt, вспомогательный объект действительно нужен UNCODE модуль. если не

Да, код может продолжать работать, но некоторые строки будут усечены под пользовательским интерфейсом детектора.

К счастью, потому что мы использовали ATL, перекомпиляция в Uncode только из меню сборки группы активной конфигурации.

Выберите соответствующие параметры. Тогда вам нужно создать и опубликовать две различные версии для вашего браузера помощи объектов: Windows9x

версия ANSI и версия WindowsNT Unicode.

 
Технический Глоссарий Ввод Shell

Теперь мы рассмотрели три способа доступа к адресной оболочке пространства. Следующая таблица представляет собой краткое изложение технического, что позволяет пересекать эти технологии.

 
фактор

Обязательный

SHLoadInProc()

аксессуар

Обратная совместимость

Shell 4.00

 Shell 4.00

Shell 4.71

механизм деятельности

Programmatically

Programmatically

ОБОЛОЧКА автоматически загружается

Реестр конфликт

None

регистрация Общие COM объект

Общая регистрация COM объект плюс доступность объекта специальной регистрации

структура кода

На основе полного крюка

COM объект со специальным интерфейсом

Реализовать IObjectWithsite

Интерфейс COM объект

Связь с основной программой

деление на подклассы

деление на подклассы

IUnknown интерфейс, с помощью основной программы

Требуется знание

программирование Win32

программирования Win32 и минимальные возможности COM

программирования Win32 и хорошее знание COM

 
резюме

В этой главе мы исследовали различные методы вторжения территории Shell и изменения его поведения, а также обзор изменений оболочки. С перевала

Зная объект, он позволяет детектору знать об изменениях в файловой системе, а затем привлечь уведомление оболочки, это более распространенный способ достижения того же эффекта.

Метод (на самом деле они совершенно разные, но их цели являются общими).

Во-вторых, мы исследуем тему коммуникации в рамках процесса, исследование подклассов и крючков, и дать пример полезности — обнаружение

Ускоритель клавиатуры, эта программа позволяет использовать новые папки, которые будут созданы, нажав одну клавишу. Мы также продемонстрировать использование одной функции оболочки API.

Способ введения соединения оболочки. Тогда мы увидели замену кнопки «Пуск» и изменения в интерфейсе программ Win32.

Отказ Включает в себя самостоятельно рисунке меню управления, теги инструментов и кнопки. Наконец, мы вводим браузер вспомогательный объект — усовершенствованный детектор и

Способ поведения браузера. В общем, мы объясним:

Как получить уведомление о файловых системах

Как ввести адрес оболочки пространство

Как начать «начать» кнопку

Как добиться полностью настроить меню

Разница между shloadinproc () и вспомогательные объекты браузера

 
========

Обработчик Context menu позволяет добавить новые пункты в меню, появляющееся при нажатии правой кнопки мыши на файле или директории. Возможно создание не только отдельных новых пунктов, но и целых вложенных меню с множеством пунктов.

В библиотеке Shell Ace обработчик Context menu реализует следующие интерфейсы:

  • IContextMenu
  • IContextMenu2
  • IContextMenu3
  • IShellExtInit

Для создания проекта расширения необходимо добавить в проект модуль с обработчиком Context menu. Для этого выберите соответствующую иконку на вкладке Shell extension:

Создание обработчика context menu

Появится окно с предложением ввести имя класса и выбрать дополнительные перекрываемые методы:

Методы обработчика context menu

После нажатия на кнопку OK в проект будет добавлен модуль с каркасом обработчика. При включении опции Create sample помимо каркаса обработчика будут создан пример готового расширения оболочки, который можно использовать для изучения библиотеки.

В обработчике можно перекрывать следующие виртуальные процедуры и функции:

procedure Initialize;

Процедура инициализации обработчика, вызывается один раз при создании экземпляра обработчика.

Если создаваемое расширение не содержит пункта меню по умолчанию, то можно оптимизировать работу Windows, установив в этом методе значение свойства MayChangeDefaultMenu в значение False.

procedure Clear;

Процедура вызывается при завершении работы с текущим списком файлов, переданных в обработчик. Может вызываться дважды, см. ниже.

class function GetClassID: TCLSID;

Функция должна возвращать уникальный идентификатор обработчика. Библиотека Shell Ace изначально генерирует уникальный идентификатор при генерации шаблона обработчика, поэтому менять его нет необходимости.

class function GetDescription: UnicodeString;

Функция должна возвращать описание обработчика.

procedure FillProgIDList(AList: TStrings);

В процедуре должно происходить заполнение списка AList ключами реестра, в которые будет прописан обработчик при регистрации расширения. Регистрация происходит в раздел реестра HKEY_CLASSES_ROOT. Например, если будет добавлен ключ .bmp и будет соответствовать всем файлам, имеющим расширение bmp, то расширение будет прописано в ветку HKEY_CLASSES_ROOT.bmpShellExContextMenuHandlers, а если будет добавлен ключ SystemFileAssociationsAudio, то расширение будет прописано в ветку HKEY_CLASSES_ROOTSystemFileAssociationsAudioShellExContextMenuHandlers и будет соответствовать всем файлам, расширения которых имеют PerceivedType Audio.

Примеры ключей реестра:

Ключ реестра Примечание
ProgID
.Расширение
SystemFileAssociations.Расширение
SystemFileAssociationsPerceivedType
Kind.Kind
Unknown Файл, не имеющий описанного в реестве расширения
* Любой файл
Directory Физическая директория
Folder Виртуальная директория

В общем случае рекомендуется регистрировать расширение на ProgID расширения файла.

procedure CreateMenu(AMenu: TdecMenu; AFlags: TdecContextMenuFlags);

Процедура должна создать дерево пунктов меню, включая вложенные в подменю. Процедура вызывается в реализации метода QueryContextMenu интерфейса IContextMenu.

Для формирования меню можно дополнительно анализировать флаги AFlags. Тип TdecContextMenuFlags определен следующим образом:

TdecContextMenuFlag = (cmfDefaultOnly, cmfVerbsOnly, cmfExplorer, cmfNoVerbs, cmfNoDefault, cmfItemMenu, cmfExtendedVerbs, cmfDisabledVerbs, cmfAsyncVerbState, cmfOptinizaForInvoke, cmfSyncCascadeMenu, cmfDoNotPickDefault);
TdecContextMenuFlags = set of TdecContextMenuFlag;

Каждый из элементов множества соответствует соответствующему флагу, переданному в метод QueryContextMenu:

Значение WinAPI флаг Описание
cmfDefaultOnly CMF_DEFAULTONLY Оболочка просит добавить только пункт меню по умолчанию. Библиотека Shell Ace самостоятельно обрабатывает этот флаг — независимо от того, сколько пунктов было добавлено, библиотека оставит только один пункт, имеющий значение свойства Default равное True.
cmfVerbsOnly CMF_VERBSONLY The shortcut menu is that of a shortcut file
cmfExplore CMF_EXPLORE The Windows Explorer tree window is present.
cmfNoVerbs CMF_NOVERBS This flag is set for items displayed in the Send To menu. Shortcut menu handlers should ignore this value.
cmfNoDefault CMF_NODEFAULT No item in the menu has been set as the default. A drag-and-drop handler should ignore this flag. A namespace extension should not set any of the menu items as the default.
cmfItemMenu CMF_ITEMMENU The calling application is invoking a shortcut menu on an item in the view (as opposed to the background of the view). Windows Server 2003 and Windows XP: This value is not available.
cmfExtendedVerbs CMF_EXTENDEDVERBS The calling application wants extended verbs. Normal verbs are displayed when the user right-clicks an object. To display extended verbs, the user must right-click while pressing the Shift key.
cmfDisabledVerbs CMF_DISABLEDVERBS The calling application intends to invoke verbs that are disabled, such as legacy menus. Windows Server 2003 and Windows XP: This value is not available.
cmfAsyncVerbState CMF_ASYNCVERBSTATE The verb state can be evaluated asynchronously. Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP: This value is not available.
cmfOptinizaForInvoke CMF_OPTIMIZEFORINVOKE Оболочка просит добавить в меню только те пункты, для которых установлено свойство Verb. Библиотека Shell Ace самостоятельно обрабатывает этот флаг — все пункты меню, у которых свойство Verb имеет пустое значение, будут автоматически удалены.
cmfSyncCascadeMenu CMF_SYNCCASCADEMENU Populate submenus synchronously. Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP: This value is not available.
cmfDoNotPickDefault CMF_DONOTPICKDEFAULT When no verb is explicitly specified, do not use a default verb in its place. Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP: This value is not available.

Добавление пункта происходит путем вызова метода Add объекта AMenu, который возвращает объект класса TdecMenuItem:

var MenuItem: TdecMenuItem;
MenuItem := AMenu.Add(CommandID, 'Caption');

где CommandID является уникальным в рамках данного обработчика идентификатором команды, а Caption является текстом, который будет выводиться в пункте меню. После добавления пункта он должен быть инициализирован путем присвоения свойствам нужных значений. Доступны следующие свойства:

Наименование Описание
Caption: UnicodeString

Определяет текст, который будет выводиться в пункте меню.

Help: UnicodeString

Определяет описание команды, которое будет выводится в строке статуса. Также данная строка используется в качестве всплывающей подсказки при добавлении данной команды в панель инструментов программы Проводник.

Verb: UnicodeString

Определяет сокращенное название действия, например, print или open. Используется при поиске команды при открытии файла программно.

Icon: HICON

Определяет иконку, которая будет отображаться в данном пункте меню.

IconFileName: UnicodeString

В случае, если свойство Icon не определено (равно нулю), то определяет имя файла и индекс ресурса, в котором содержится иконка, которая будет отображаться в данном пункте меню. Для определения иконки рекомендуется использовать данное свойство, а не свойство Icon, поскольку это позволит программе Проводник отображать иконку команды при добавлении ее в панель инструментов.

AutoIconSize: Boolean

Определяет, что размеры иконки элемента меню будут автоматически увеличиваться или уменьшаться до размеров, определенных системой. По умолчанию значение свойства установлено в True, менять его не рекомендуется. Свойство проявляет себя в нестандартных визуальных темах оформления, в которых размер шрифта в меню больше или меньше стандартного, или при увеличенном DPI экрана.

Так выглядит меню с добавленными пунктами Register и Unregister при стандартном DPI, равном 96:

Контекстное меню при DPI 96

Так выглядит меню при увеличенном DPI, равном 150, с AutoIconSize равном False:

Контекстное меню при DPI 150 c AutoIconSize равном False

А так выглядит меню при увеличенном DPI, равном 150, с AutoIconSize равном True:

Контекстное меню при DPI 150 AutoIconSize равном True

Default: Boolean

Определяет, что данный пункт меню является пунктом меню по умолчанию, при прорисовке выделяется утолщенным шрифтом. Только один пункт меню может являться пунктом меню по умолчанию. Если иное расширение оболочки раньше создало пункт меню по умолчанию, то данное свойство будет проигнорировано.

Enabled: Boolean

Определяет, что данный пункт меню разрешен для вызова. По умолчанию имеет значение True.

Visible: Boolean

Определяет, что данный пункт меню является видимым. По умолчанию имеет значение True.

Checked: Boolean

Определяет, что пункт меню будет отмечен галочкой.

RadioCheck: Boolean

Определяет, что в случае, если свойство Checked равно True, то вместо галочки будет использоваться точка.

OwnerDraw: Boolean

Определяет, что пункт меню имеет программную прорисовку, при этом должны быть реализованы методы GetItemSize и DrawItem.

При использовании программной прорисовки Windows Vista и более современные системы будут игнорировать текущую визуальную тему и будут прорисовывать меню в классическом стиле. Так выглядит контекстное меню, прорисованное с использованием визуальной темы:

Контекстное меню, прорисованное с использованием визуальной темы

А так выглядит контекстное меню с добавленным пунктом, имеющим программную прорисовку:

Контекстное меню с добавленным пунктом, имеющим программную прорисовку

Добавление пунктов по вложенные меню происходит при вызове метода Add свойства SubMenu:

MenuItem2 := MenuItem.SubMenu.Add(CommandID2);

Построение меню может происходить в зависимости от количества или типа файлов, переданных в обработчик. Список переданных файлов можно получить вызовом метода CreateCurrentFileList. Функция возвращает объект класса TStrings, содержащий список файлов. В версиях Delphi вплоть до версии 2009, в которых тип string равен типу AnsiString, имена файлов в списке хранятся в формате UTF8. Объект должен быть уничтожен после его обработки. Также доступны функции GetCurrentFileListCount, которая возвращает количество файлов, и GetFirstOfCurrentFileList, которая возвращает первый элемент списка (с нулевым индексом).

function CreateItemIcon(AMenuItem: TdecMenuItem; const AIconSize: TSize): HICON;

Функция должна вернуть идентификатор (handle) иконки, которая будет ассоциирована с пунктом меню, в случае отсутствия иконки Функция должна вернуть 0. Значение свойства AMenuItem.ID определяет, для какого пункта меню нужно создать иконку.

Параметр AIconSize определяет рекомендуемые размеры иконки.

Для пунктов меню, имеющих свойство AutoIconSize равное True можно создать иконку любого размера, ее размер при прорисовке будет изменет автоматически до рекомендованного Windows.

Необходимости удалять иконку из памяти нет, поскольку по окончанию работы с иконкой библиотека Shell Ace сама удалит все ресурсы, связанные с иконкой.

В ОС Windows XP и более ранних версиях Windows иконка не может быть ассоциирована с пунктами меню, имеющими вложенные меню. В Windows Vista и более современных системах эта проблема отсутствует.

Если у вас в среде разработки установлен пакет Graphics32, то при использовании иконок в контекстном меню рекомендуется добавлять в проект модуль decShellExtensionGraphics32. Это позволит обработчику использовать более плавные процедуры сглаживания иконок при увеличении или уменьшении их размеров. Это проявляется при прорисовках пунктов меню с иконками и свойством AutoIconSize равным True в режимах работы с увеличенным DPI экрана.

Так выглядит меню с добавленными пунктами Register и Unregister при увеличенном DPI, равном 150, с AutoIconSize равном True без использования модуля decShellExtensionGraphics32:

Контекстное меню без использования модуля decShellExtensionGraphics32

А так выглядит меню при увеличенном DPI, равном 150, с AutoIconSize равном True с использованием модуля decShellExtensionGraphics32:

Контекстное меню с использованием модуля decShellExtensionGraphics32

Если библиотека Shell Ace обнаружит установленный пакет Graphics32, то модуль decShellExtensionGraphics32 будет автоматически добавлен в список используемых модулей при создании каркаса обработчика.

function GetItemSize(AMenuItem: TdecMenuItem): TSize;

Метод вызывается для определения размеров пунктов меню, имеющих режим DrawMode равный dmCustom. Значение свойства AMenuItem.ID определяет, размеры какого именно пункта меню нужно определить.

procedure DrawItem(AMenuItem: TdecMenuItem; ADC: HDC; const ARect: TRect; ADrawState: TOwnerDrawState);

Метод вызывается для прорисовки пунктов меню, имеющих режим DrawMode равный dmCustom. Свойство AMenuItem.ID определяет, какой именно пункта меню нужно прорисовать. Библиотека Shell Ace самостоятельно отрисовывает фон пункта меню в соответствии с цветовой схемой, используемой в системе.

Параметр ADC определяет контекст, в котором нужно рисовать. Параметр ARect определяет положение и размеры области, отведенной для пункта меню. Размеры области могут быть больше или меньше, чем полученные в функции GetItemSize. Параметр ADrawState определяет стиль, в котором нужно прорисовать пункт меню.

function ExecuteCommand(AMenuItem: TdecMenuItem; AInfo: PShellExecuteInfoW; ATitle: UnicodeString; AShiftState: TShiftState; APoint: PPoint): Boolean;

Функция вызывается при выборе пользователем пункта меню, свойство AMenuItem.ID определяет, какой именно пункта меню был выбран. В этой функции необходимо реализовать непосредственное выполнение команды. В параметре AInfo передаются ссылка на запись, которая может использоваться при вызове системной функции ShellExecuteExW. Нижеперечисленные поля записи могут быть инициализированы, остальные поля содержат значение 0:

Наименование Описание
cbSize: DWORD SizeOf(ЕShellExecuteInfoW)
fMask: ULONG Комбинация флагов SEE_MASK_ICON, SEE_MASK_HOTKEY, SEE_MASK_NOCLOSEPROCESS, SEE_MASK_CONNECTNETDRV, SEE_MASK_NOASYNC, SEE_MASK_FLAG_NO_UI, SEE_MASK_NO_CONSOLE, SEE_MASK_HASLINKNAME, SEE_MASK_HASTITLE, SEE_MASK_ASYNCOK, SEE_MASK_HMONITOR, SEE_MASK_NOZONECHECKS, SEE_MASK_WAITFORINPUTIDLE и SEE_MASK_FLAG_LOG_USAGE. При использовании этого параметра рекомендуется отфильтровывать флаги, которые нужны для обработки команды.
Wnd: HWND Идентификатор (хендл) окна, которое следует использовать как родительское при UI операциях.
lpParameters: LPCWSTR Параметры
lpDirectory: LPCWSTR Рабочая директория
nShow: Integer SW_SHOW или альтернативный флаг
hkeyClass: HKEY
dwHotKey: DWORD Код горячей клавиши, которая будет ассоциирована с запускаемым приложением. Значение валидно, только если fMask содержит флаг CMIC_MASK_HOTKEY.
hIcon: THandle Идентификатор (handle) иконки, которая может использоваться вызываемым приложением в качестве иконки приложения. Значение валидно, только если fMask содержит флаг CMIC_MASK_ICON.

ATitle определяет строку, которая может использоваться запускаемым приложением в качестве заголовок главного окна, начиная с Windows Vista не используется. AShiftState определяет состояние клавиш Alt, Ctrl и Shift. Указатель APoint указывает на абсолютные координаты мыши в момент вызова команды пользователем, может быть равен nil.

Список файлов для обработки НУЖНО получать методом CreateCurrentFileList, поскольку он может отличаться в большую сторону от того списка, который был получен в методе CreateMenu. Это происходит потому, что при вызове пользователем меню для большого количества файлов Windows для создания меню передает лишь часть списка, а уже при вызове команды передает весь список. Поэтому НЕ кэшируйте список, а всегда вызывайте функцию CreateCurrentFileList повторно!

Обязательными для реализации в обработчике Context menu являются следующие методы:

  • GetClassID
  • FillProgIDList
  • CreateMenu
  • ExecuteCommand

Смотрите также:

  • Что такое расширение оболочки
  • Какие бывают расширения оболочки
  • Как создать расширение оболочки
  • Инициализация расширений оболочки
  • Как создать расширение оболочки Context menu
  • Как создать расширение оболочки Drag and drop context menu
  • Как создать расширение оболочки Drop target
  • Как создать расширение оболочки Icon
  • Как создать расширение оболочки Info tip
  • Как создать расширение оболочки Overlay icon
  • Как создать расширение оболочки Preview
  • Как создать расширение оболочки Property sheet
  • Как создать расширение оболочки Property store
  • Как создать расширение оболочки Thumbnail
  • Как зарегистрировать расширение оболочки
  • Как отлаживать расширение оболочки
  • Использование логов

Like this post? Please share to your friends:
  • Расширенный диспетчер задач для windows 10 скачать
  • Расширение кодек hevc для windows 10
  • Расширение заархивированных файлов в операционной системе windows
  • Расширенный буфер обмена для windows 10
  • Расширение для фото румс windows 10 скачать бесплатно