Главная > Методическое пособие


XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,

где X – шестнадцатеричная цифра. Для повышения удобства использования утилиты используются различные ключи и параметры, задаваемые в командной строке. В таблице 6.1 приведено описание ключей UUIDGEN.

Таблица 6.1 – ключи утилиты UUIDGEN.

Ключ

Назначение

Пример
использования

–i

Вывод UUID в виде шаблона IDL

uuidgen –i

–s

Вывод UUID в виде инициализированной структуры языка C.

uuidgen –s

–o

Вывод UUID в указанный файл

uuidgen –omyfile.txt

–n

Количество генерируемых UUID

uuidgen –n100

–v

Отображение версии программы

uuidgen –v

–h, –?

Вывод информации о ключах программы

uuidgen –h

IDL – это язык определения интерфейсов (Interface Definition Language), используемый как для создания COM серверов, так и для написания программ, использующих вызовы удаленных процедур (Remote Procedure Calling – RPC). Для упрощения написания COM сервера язык IDL в лабораторной работе использоваться не будет.

Наиболее удобной является опция UUIDGEN, позволяющая генерировать UUID в виде инициализированной структуры языка C. Результат выполнения утилиты в этом случае выглядит следующим образом:

INTERFACENAME = { /* a640e00b-beb9-4fa4-80d1-56bd7c65ec20 */

0xa640e00b,

0xbeb9,

0x4fa4,

{0x80, 0xd1, 0x56, 0xbd, 0x7c, 0x65, 0xec, 0x20}

};

INTERFACENAME заменяется на имя конкретного CLSID. Ниже представлен пример определения CLSID в программе:

GUID CLSID_MyClass = { /* a640e00b-beb9-4fa4-80d1-56bd7c65ec20 */

0xa640e00b,

0xbeb9,

0x4fa4,

{0x80, 0xd1, 0x56, 0xbd, 0x7c, 0x65, 0xec, 0x20}

};

Тип GUID предназначен для определения глобальных уникальных идентификаторов. Отметим, что понятия UUID, GUID, IID и CLSID используются в различных контекстах, но имеют одинаковую структуру и представляют собой последовательность шестнадцатеричных цифр в указанном выше формате.

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

class имя_класса: public имя_интерфейса1, имя_интерфейса_2, …

{

public:

описание методов интерфейсов

};

Предопределенный COM интерфейсы, такие как IUnknown и IClassFactory, описаны в заголовочном файле COMBASE.H. Интерфейсы расширения оболочки описаны в заголовочном файле SHLOBJ.H.

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

class CMyClassFactory: public IClassFactory

{

protected:

ULONG m_cRef;

public:

CIconViewClassFactory();

~CIconViewClassFactory();

STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);

STDMETHODIMP_(ULONG) AddRef();

STDMETHODIMP_(ULONG) Release();

STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *);

STDMETHODIMP LockServer(BOOL);

};

Переменная класса m_cRef используется для подсчета количества ссылок. Поскольку интерфейс IClassFactory наследует интерфейс IUnknown, включать IUnknown в описание базовых интерфейсов класса не обязательно. STDMETHODIMP и STDMETHODIMP_(type) – это макросы, определения которых выглядят следующим образом:

#define STDAPIVCALLTYPE __export __cdecl

#define STDMETHODIMP HRESULT STDMETHODCALLTYPE

#define STDMETHODIMP_(type) type STDMETHODCALLTYPE

Эти макросы используются со всеми методами реализуемых интерфейсов. Отличие STDMETHODIMP от STDMETHODIMP_(type) заключается в том, что STDMETHODIMP определяет метод, возвращающий значение типа HRESULT, а STDMETHODIMP_(type) определяет метод, возвращающий значение типа type. В приведенном выше примере метод AddRef возвращает значение типа ULONG.

Класс, реализующий методы интерфейса IClassFactory, должен быть определен в любом COM сервере. Данный клас, как правило, выполняет одинаковые действия для всех COM серверов и его реализация может выглядеть следующим образом:

CMyClassFactory::CMyClassFactory()

{

m_cRef = 0L;

g_cRefThisDll++;

}

CMyClassFactory::~CMyClassFactory()

{

g_cRefThisDll--;

}

STDMETHODIMP CMyClassFactory::QueryInterface(REFIID riid,

LPVOID FAR *ppv)

{

*ppv = NULL;

if (IsEqualIID(riid, IID_IUnknown) ||

IsEqualIID(riid, IID_IClassFactory))

{

*ppv = (LPCLASSFACTORY)this;

AddRef();

return NOERROR;

}

return E_NOINTERFACE;

}

STDMETHODIMP_(ULONG) CMyClassFactory::AddRef()

{

return ++m_cRef;

}

STDMETHODIMP_(ULONG) CMyClassFactory::Release()

{

if (--m_cRef) return m_cRef;

delete this;

return 0;

}

STDMETHODIMP CMyClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,

REFIID riid, LPVOID *ppvObj)

{

*ppvObj = NULL;

if (pUnkOuter) return CLASS_E_NOAGGREGATION;

CMyClass *pMyClass = new CMyClass();

if (!pMyClass) return E_OUTOFMEMORY;

return pMyClass->QueryInterface(riid, ppvObj);

}

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

В деструкторе CMyClassFactory количество ссылок на объект данного класса уменьшается на 1.

В реализации метода IUnknown::QueryInterface проверяется, является ли указанный IID идентификатором интерфейса IUnknown или IClassFactory. Если это так, то возвращается указатель на объект класса CMyClassFactory и вызывается метод AddRef, увеличивающий количество ссылок на объект класса CMyClassFactory. В противном случае возвращается код ошибки. Константы IID_IUnknown и IID_IClassFactory определяют IID предопределенных интерфейсов IUnknown и IClassFactory.

В реализации метода AddRef количество ссылок на объект данного класса увеличивается на 1 и возвращается текущее значение количества ссылок.

В реализации метода Release количество ссылок на объект данного класса уменьшается на 1 и возвращается текущее значение количества ссылок, если оно не равно 0. В противном случае вызывается деструктор объекта.

Реализация метода IClassFactory::CreateInstance создается экземпляр класса CMyClass и возвращается указатель на запрашиваемый интерфейс, реализуемый классом CmyClass. Аргумент pUnkOuter служит для поддержки агрегирования, но в данной реализации IClassFactory агрегирование не поддерживается и если pUnkOuter != NULL возвращается код ошибки.

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

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

STDMETHODIMP CMyClass::Initialize(LPCITEMIDLIST pIDFolder,

LPDATAOBJECT pDataObj, HKEY hRegKey)

{

STGMEDIUM medium;

HRESULT hr = 0;

FORMATETC fmte = {CF_HDROP,

(DVTARGETDEVICE FAR *)NULL, DVASPECT_CONTENT,

-1, TYMED_HGLOBAL};

if (pDataObj) hr = pDataObj->GetData(&fmte, &medium);

if (SUCCEEDED(hr))

DragQueryFile((HDROP)medium.hGlobal, 0,

m_szFileName, sizeof(m_szFileName));

return hr;

}

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

Аргумент pDataObj является указателем на интерфейс IDataObject, идентифицирующий объект, для которого вызывается расширение оболочки. Объектом может быть, например, файл или папака. В данной реализации значение интерфейс IDataObject используется для получения имени файла, для которого было вызвано контекстное меню. Функция DragQueryFile используется для непосредственного получения имени файла и записи его в переменную класса m_szFileName.

DLL библиотека, содержащая реализацию COM сервера должна экспортировать две функции: DllCanUnloadNow и DllGetClassObject. Функция DllCanUnloadNow вызывается оболочкой для определения момента выгрузки DLL библиотеки из памяти. Функция DllGetClassObject вызывается оболочкой для получения указателя на интерфейс IClassFactory, реализуемый классом COM сервера. Помимо двух экспортируемых функций DLL библиотека также включает в себя функцию DllMain, вызываемую операционной системой при подключении библиотеки к процессу или потоку, а также при отключении от процесса или потока.

Реализация функци DllMain, DllCanUnloadNow и DllGetClassObject может выглядеть следующим образом:

BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason,

LPVOID lpReserved)

{

if (dwReason == DLL_PROCESS_ATTACH)

{

g_hmodThisDll = hModule;

}

return TRUE;

}

STDAPI DllCanUnloadNow()

{

return (!g_cRefThisDll ? S_OK : S_FALSE);

}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)

{

*ppvOut = NULL;

if (IsEqualIID(rclsid, CLSID_MyClass))

{

CMyClassFactory *pcf = new CMyClassFactory;

return pcf->QueryInterface(riid, ppvOut);

}

return CLASS_E_CLASSNOTAVAILABLE;

}

Переменная g_hmodThisDll используется для хранения дескриптора данной DLL библиотеки.

Функция DllCanUnloadNow возвращает значение S_OK, когда количество ссылок на библиотеку равно 0 и S_FALSE в противном случае.

Функция DllGetClassObject создает экземпляр класса, реализующего методы интерфейса IClassFactory и возвращает указатель на запрошенный интерфейс. Если указанный CLSID не равен CLSID класса, реализуемого данным COM сервером, возвращается код ошибки.

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

Интерфейс определяет три метода: GetCommandString, InvokeCommand и QueryContextMenu.

Метод IContextMenu::QueryContextMenu предназначен для добавления пунктов в контекстное меню. Определение метода выглядит следующим образом:

HRESULT QueryContextMenu(

HMENU hmenu,

UINT indexMenu,

UINT idCmdFirst,

UINT idCmdLast,

UINT uFlags

);

hmenu – дескриптор контекстного меню, используется со всеми операциями добавления пунктов меню.

indexMenu – позиция, в которую можно добавить пункт меню.

idCmdFirst – минимальное значение идентификатора пункта меню, который назначается расширением оболочки.

idCmdLast – максимальное значение идентификатора пункта меню, который назначается расширением оболочки.

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

Конкретный идентификатор пункта меню должен быть в диапазоне от idCmdFirst до idCmdLast.

Ниже представлен пример реализации метода IContextMenu::QueryContextMenu.

STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu,

UINT indexMenu,

UINT idCmdFirst,

UINT idCmdLast,

UINT uFlags)

{

UINT idCmd = idCmdFirst;

char szMenuText[64];

lstrcpy(szMenuText, "&Пункт меню");

InsertMenu(hMenu, indexMenu++,

MF_SEPARATOR|MF_BYPOSITION, 0, NULL);

InsertMenu(hMenu, indexMenu, MF_STRING|MF_BYPOSITION,

idCmdFirst, szMenuText);

return (HRESULT)1;

}

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

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

HRESULT GetCommandString(

UINT idCmd,

UINT uFlags,

UINT *pwReserved,

LPSTR pszName,

UINT cchMax

);

idCmd – смещение идентификатора пункта меню. Для первого добавленного ранее пункта меню значение idCmd равно 0, для второго – 1 и т. д. Используется для идентификации выделенного пункта меню.

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

pwReserved – зарезервированный аргумент, не должен использоваться.

pszName – адрес буфера, используемого для записи текстовой подсказки к пункту меню.

cchMax – размер буфера (в символах), указываемого аргументом pszName.

Ниже представлен пример реализации метода IContextMenu::GetCommandString.

STDMETHODIMP CShellExt::GetCommandString(UINT idCmd,

UINT uFlags,

UINT FAR *reserved,

LPSTR pszName,

UINT cchMax)

{

If (idCmd == 0) lstrcpy(pszName, "Новый пункт меню №1");

return NOERROR;

}

Метод IContextMenu::InvokeCommand вызывается оболочкой при выборе добавленного ранее пункта меню. Определение метода выглядит следующим образом:

HRESULT InvokeCommand(

LPCMINVOKECOMMANDINFO lpici

);

lpici – указатель на структуру CMINVOKECOMMANDINFO, содержащую информацию о выполняемой команде.

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

Поле hwnd структуры определяет дескриптор родительского окна контекстного меню.

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

Ниже представлен пример реализации метода IContextMenu::InvokeCommand.

STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)

{

if (!HIWORD(lpcmi->lpVerb))

{

UINT idCmd = LOWORD(lpcmi->lpVerb);

if (idCmd == 0)

MessageBox(lpcmi->hwnd, “Выбран пункт меню №1”,

“Сообщение”, MB_OK | MB_ICONINFORMATION);

}

return NOERROR;

}

Управляющий файл реестра (с расширением .REG) используется для добавления в реестр некоторой информации. Файл представляет собой обычный текстовый файл с секциями, аналогичными файлу INI. Ниже представлен пример файла MY.REG, регистрирующий в реестре COM сервер расширения оболочки для обработки контекстного меню, связанного с текстовыми файлами.

REGEDIT4

[HKEY_CLASSES_ROOT\CLSID\{87b9bd00-c65c-11cd-a259-00dd010e8c28}]

@="Shell Extension Sample"

[HKEY_CLASSES_ROOT\CLSID\{87b9bd00-c65c-11cd-a259-00dd010e8c28}\InProcServer32]

@="shellext.dll"

"ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\txtfile\shellex\ContextMenuHandlers]

@="MyContextMenu"

[HKEY_CLASSES_ROOT\txtfile\shellex\ContextMenuHandlers\MyContextMenu]

@="{87b9bd00-c65c-11cd-a259-00dd010e8c28}"

Сначала регистрируется COM сервер (файл shellext.dll) в разделе HKEY_CLASSES_ROOT\CLSID реестра. Затем для текстовых файлов (раздел HKEY_CLASSES_ROOT\txtfile) в подразделе ContextMenuHandlers создается подраздел MyContextMenu, в значении по умолчанию которого указывается CLSID COM сервера.

Если необходимо в раздел HKEY_CLASSES_ROOT добавить информацию о новом типе (расширении) файла, можно использовать следующую последовательность команд в управляющем файле реестра:

[HKEY_CLASSES_ROOT\.<расширение>]

@="<имя_расширения>"

[HKEY_CLASSES_ROOT\<имя_расширения>]

@="<описание расширения>"

Например, для расширения .123 используются команды:

[HKEY_CLASSES_ROOT\.123]

@="123File"

[HKEY_CLASSES_ROOT\123File]

@="123 File Extension"

Для добавления информации в реестр необходимо просто запустить .REG файл из проводника Windows.

Для реализации COM сервера рекомендуется использовать среду разработки Microsoft Visual C++.

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

  1. Для чего предназначена модель COM?

  2. Что такое интерфейс, реализация интерфейса, объект?

  3. Для чего служит интерфейс IUnknown?

  4. Какие существуют потоковые модели?

  5. Как можно создать COM объект?

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

6.5. Варианты заданий на лабораторную работу

  1. Добавить в контекстное меню файлов с расширением .txt пункт «Информация о файле». При выборе пункта на экране должно отображаться сообщение о количестве строк в текстовом файле.

  2. Добавить в контекстное меню файлов с расширением .exe пункт «Выполнить». При выборе пункта должен осуществляться запуск соответствующего приложения. Для запуска приложения использовать функцию Win32 API ShellExecute.

  3. Добавить в контекстное меню файлов с расширением .doc пункт «Печать». При выборе пункта должна осуществляться распечатка соответствующего документа. Для распечатки документа использовать функцию Win32 API ShellExecute.

  4. Добавить в контекстное меню файлов с расширением .tmp пункт «Удалить». При выборе пункта соответствующий файл должен удаляться. Для удаления файла использовать функцию Win32 API DeleteFile.

  5. Добавить в контекстное меню файлов с расширением .dir пункт «Записать содержимое папки». При выборе пункта в соответствующий файл должны записываться имена всех файлов текущей папки. Для поиска файлов по шаблону использовать функции Win32 API FindFirstFile и FindNextFile.

6.6. Пример программы

Далее представлен пример программы-расширения оболочки, реализованной в виде COM сервера. Программа добавляет в контекстное меню для файлов с расширением .txt пункт «Просмотр». При выборе данного пункта на экране отображается диалоговое окно с содержимым текстового файла. Программа реализована в среде Microsoft Visual C++ 6.0.

Файл TXTView.h

#ifndef _TXTVIEW_H

#define _TXTVIEW_H

#include <windows.h>

#include <windowsx.h>

#include <shlobj.h>

extern GUID CLSID_TXTView;

extern char szFileName[MAX_PATH];

class CTXTViewClassFactory: public IClassFactory

{

protected:

ULONG m_cRef;

public:

CTXTViewClassFactory();

~CTXTViewClassFactory();

STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);

STDMETHODIMP_(ULONG) AddRef();

STDMETHODIMP_(ULONG) Release();

STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *);

STDMETHODIMP LockServer(BOOL);

};

class CTXTView: public IContextMenu, IShellExtInit

{

protected:

ULONG m_cRef;

public:

CTXTView();

~CTXTView();

STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);

STDMETHODIMP_(ULONG) AddRef();

STDMETHODIMP_(ULONG) Release();

STDMETHODIMP GetCommandString(UINT idCmd, UINT uFlags,

UINT *pwReserved, LPSTR pszName, UINT cchMax);

STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);

STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu,

UINT idCmdFirst, UINT idCmdLast, UINT uFlags);

STDMETHODIMP Initialize(LPCITEMIDLIST pIDFolder,

LPDATAOBJECT pDataObj, HKEY hKeyID);

};

#endif

Файл StdAfx.h

// stdafx.h : include file for standard system include files,

// or project specific include files that are used frequently, but

// are changed infrequently

//

#if !defined(AFX_STDAFX_H__5CE57FCA_CE76_4558_AA88_2D4491EDA0D1__INCLUDED_)

#define AFX_STDAFX_H__5CE57FCA_CE76_4558_AA88_2D4491EDA0D1__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

// Insert your headers here

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#include <windows.h>

// TODO: reference additional headers your program requires here

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__5CE57FCA_CE76_4558_AA88_2D4491EDA0D1__INCLUDED_)

Файл TXTView.cpp

// TXTView.cpp : Defines the entry point for the DLL application.

//

#include "stdafx.h"

#include <shellapi.h>

#include "TXTView.h"

UINT g_cRefThisDll = 0;

HINSTANCE g_hmodThisDll = NULL;

GUID CLSID_TXTView = {

0xa640e00b,

0xbeb9,

0x4fa4,

{0x80, 0xd1, 0x56, 0xbd, 0x7c, 0x65, 0xec, 0x20}

};

BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason,

LPVOID lpReserved)

{

if (dwReason == DLL_PROCESS_ATTACH)

{

g_hmodThisDll = hModule;

}

return TRUE;

}

STDAPI DllCanUnloadNow()

{

return (!g_cRefThisDll ? S_OK : S_FALSE);

}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)

{

*ppvOut = NULL;

if (IsEqualIID(rclsid, CLSID_TXTView))

{

CTXTViewClassFactory *pcf = new CTXTViewClassFactory;

return pcf->QueryInterface(riid, ppvOut);

}

return CLASS_E_CLASSNOTAVAILABLE;

}

CTXTViewClassFactory::CTXTViewClassFactory()

{

m_cRef = 0L;

g_cRefThisDll++;

}

CTXTViewClassFactory::~CTXTViewClassFactory()

{

g_cRefThisDll--;

}

STDMETHODIMP CTXTViewClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv)

{

*ppv = NULL;

if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))

{

*ppv = (LPCLASSFACTORY)this;

AddRef();

return NOERROR;

}

return E_NOINTERFACE;

}

STDMETHODIMP_(ULONG) CTXTViewClassFactory::AddRef()

{

return ++m_cRef;

}

STDMETHODIMP_(ULONG) CTXTViewClassFactory::Release()

{

if (--m_cRef) return m_cRef;

delete this;

return 0;

}

STDMETHODIMP CTXTViewClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,

REFIID riid,

LPVOID *ppvObj)

{

*ppvObj = NULL;

if (pUnkOuter) return CLASS_E_NOAGGREGATION;

CTXTView *pTXTView = new CTXTView();

if (!pTXTView) return E_OUTOFMEMORY;

return pTXTView->QueryInterface(riid, ppvObj);

}

STDMETHODIMP CTXTViewClassFactory::LockServer(BOOL fLock)

{

return NOERROR;

}

CTXTView::CTXTView()

{

m_cRef = 0L;

g_cRefThisDll++;

}

CTXTView::~CTXTView()

{

g_cRefThisDll--;

}

STDMETHODIMP CTXTView::QueryInterface(REFIID riid, LPVOID FAR *ppv)

{

*ppv = NULL;

if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown))

*ppv = (IShellExtInit *)this;

else if (IsEqualIID(riid, IID_IContextMenu))

*ppv = (IContextMenu *)this;

if (*ppv)

{

AddRef();

return NOERROR;

}

return E_NOINTERFACE;

}

STDMETHODIMP_(ULONG) CTXTView::AddRef()

{

return ++m_cRef;

}

STDMETHODIMP_(ULONG) CTXTView::Release()

{

if (--m_cRef) return m_cRef;

delete this;

return 0;

}

STDMETHODIMP CTXTView::Initialize(LPCITEMIDLIST pIDFolder,

LPDATAOBJECT pDataObj, HKEY hRegKey)

{

STGMEDIUM medium;

HRESULT hr = 0;

FORMATETC fmte = {CF_HDROP, (DVTARGETDEVICE FAR *)NULL, DVASPECT_CONTENT,

-1, TYMED_HGLOBAL};

if (pDataObj) hr = pDataObj->GetData(&fmte, &medium);

if (SUCCEEDED(hr))

DragQueryFile((HDROP)medium.hGlobal, 0, szFileName, sizeof(szFileName));

return hr;

}

Файл StdAfx.cpp

// stdafx.cpp : source file that includes just the standard includes

// TXTView.pch will be the pre-compiled header

// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H

// and not in this file

Файл CtxMenu.cpp

#include "stdafx.h"

#include "TXTView.h"

#include "resource.h"

#include <fstream.h>

#include <shellapi.h>

extern UINT g_cRefThisDll;

extern HINSTANCE g_hmodThisDll;

char szFileName[MAX_PATH];

BOOL CALLBACK TXTViewDlgProc(HWND, UINT, WPARAM, LPARAM);

void ReadFile(HWND hList);

STDMETHODIMP CTXTView::QueryContextMenu(HMENU hMenu, UINT indexMenu,

UINT idCmdFirst, UINT idCmdLast,

UINT uFlags)

{

UINT idCmd = idCmdFirst;

char szMenuText[64];

lstrcpy(szMenuText, "&Ïðîñìîòð");

InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);

InsertMenu(hMenu, indexMenu, MF_STRING|MF_BYPOSITION,

idCmdFirst, szMenuText);

return (HRESULT)1;

}

STDMETHODIMP CTXTView::GetCommandString(UINT idCmd, UINT uFlags,

UINT *pwReserved, LPSTR pszName,

UINT cchMax)

{

if (idCmd == 0) lstrcpy(pszName,

"Âûâîä íà ýêðàí ñîäåðæèìîãî òåêñòîâîãî ôàéëà");

return NOERROR;

}

STDMETHODIMP CTXTView::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)

{

if (!HIWORD(lpcmi->lpVerb))

{

UINT idCmd = LOWORD(lpcmi->lpVerb);

if (idCmd == 0)

DialogBox(g_hmodThisDll, MAKEINTRESOURCE(IDD_TXTVIEWDIALOG),

lpcmi->hwnd, (DLGPROC)TXTViewDlgProc);

}

return NOERROR;

}

BOOL CALLBACK TXTViewDlgProc(HWND hWnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

switch (msg)

{

case WM_INITDIALOG:

ReadFile(GetDlgItem(hWnd, IDC_LIST));

break;

case WM_CLOSE:

EndDialog(hWnd, 0);

break;

case WM_COMMAND:

if (wParam == IDOK || wParam == IDCANCEL)

EndDialog(hWnd, 0);

break;

}

return 0;

}

void ReadFile(HWND hList)

{

char buf[256];

ifstream in(szFileName);

if (!in) return;

while (!in.eof())

{

in.getline(buf, sizeof(buf));

SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)buf);

}

in.close();

}

Файл TXTView.def

;txtview.def : Declares the module parameters for the DLL.

LIBRARY TXTVIEW

DESCRIPTION 'TXTView Shell Extension'

EXPORTS

DllCanUnloadNow private

DllGetClassObject private

Файл TXTView.reg

REGEDIT4

[HKEY_CLASSES_ROOT\CLSID\{a640e00b-beb9-4fa4-80d1-56bd7c65ec20}]

@="TXTView Shell Extension Sample"

[HKEY_CLASSES_ROOT\CLSID\{a640e00b-beb9-4fa4-80d1-56bd7c65ec20}\InProcServer32]

@="txtview.dll"

"ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\txtfile\shellex\ContextMenuHandlers]

@="TXTMenu"

[HKEY_CLASSES_ROOT\txtfile\shellex\ContextMenuHandlers\TXTMenu]

@="{a640e00b-beb9-4fa4-80d1-56bd7c65ec20}"



Скачать документ

Похожие документы:

  1. Том 2 документации об аукционе для проведения открытого аукциона для субъектов малого предпринимательства

    Инструкция
    ... с некоторыми операционными системами) - Вес ... Методическое пособие по ... пособием и предназначена для использования на учебных занятиях по химии, и другим общеобразовательным дисциплинам ... выполнения лабораторных работ по биологии» ... (лота), указанным в томе ...
  2. Ищите тесты не только по названиям

    Тесты
    ... методического) уровня системы ... работой всех устройств ПК и процессом выполнения прикладных программ, называется 3. Операционные системы ... дисциплины ... , лабораторное оборудование ... пособия по ... по достижении: 108. Выполнение налогоплательщиком письменных указаний ...
  3. Постановление исполнительного комитета г казани 30 06 2009 №5258 об утверждении стандарта муниципальной услуги «предоставление общедоступного бесплатного начального общего основного общего среднего (полного) общего образования по основным

    Программа
    ... Д Д - 1.4 Методическое пособие для учителя К К - 1.5 Рабочие тетради по физике Д Д - 1.6 Хрестоматия по физике К** К** По возможности 1.7 Комплекты пособий для выполнения лабораторных ...
  4. III ПРИРОДНЫЙ ЗАКОН ПИТАНИЯ ЧЕЛОВЕКА

    Закон
    ... операционный ... указанный срок подлежат увольнению по профессиональной непригодности. Обязательно выполнение ... системы и системы обмена веществ, нарушается работа всей пищеварительной системы ... наглядные пособия, ... “Дисциплина” ... методически ... У лабораторных мышей ...
  5. Методическое пособие по по дисциплине «теоретические основы автоматизированного управления» и указания к выполнению лабораторных работ

    Методическое пособие
    ... Методическое пособие по по дисциплине «Теоретические основы автоматизированного управления» и указания к выполнению лабораторных работ Номер специальности – 230102 «Автоматизированные системы ... и под различными операционными системами. При этом ...

Другие похожие документы..