Лабораторная работа
по дисциплине
«Технологии программирования»
Лабораторная работа №2
Выполнили:
Студенты группы С-75
«__»_________ 2006г
Проверил:
Преподаватель каф. ЭВА
«__»_________ 2006г
Содержание
Содержание. 2
Задание 1. 3
Подготовка DLL-модуля расширения MFC.. 3
Лист. 1. Заголовочный файл класса CToolTipCtrlEx. 3
Лист. 2. cpp-файл для класса CToolTipCtrlEx. 4
ОТЧЕТ. 6
Лист. 1. Заголовочный файл класса CToolTipCtrlEx. 6
Лист. 2. cpp-файл для класса CToolTipCtrlEx. 7
Задание 2. 8
ОТЧЕТ. 8
Заголовочный файл (DLLTEST. H) 8
Код библиотеки (DLLTEST. CPP) 8
Исходный файл приложения, использующего библиотеку DLL (Test1.EXE) 10
Работа программы.. 10
Задание 1. Создать DLL-модуль расширения MFC, который восполнил бы недостаток MFC класса CToolTipCtrl, составить программу, работающую с этим модулем.
Подготовка DLL-модуля расширения MFC
Подсказки ToolTips - это миниатюрное окно со справочным текстом, которое всплывает, когда курсор мыши устанавливается на кнопке инструментальной панели или на другом объекте интерфейса. Но поскольку функция CToolTipCtrl::AddTool не выполняет автоматически деления на подклассы окна, которому назначается подсказка ToolTip, информацию о событиях, связанных с мышью, вам приходится передавать элементу управления ToolTip самостоятельно. Это обычно означает, что задача деления окна на подклассы возлагается на вас.
Элемент управления ToolTip, который служит основой объекта CToolTipCtrl, будет самостоятельно выполнять деление на подклассы, если вы позаботитесь о передаче ему соответствующих флажков, - функция, которую команда разработчиков MFC обошла своим вниманием. К счастью, исправить эту оплошность совсем нетрудно. Надо просто подготовить класс, производный от класса CToolTipCtrl, и заменить функцию CToolTipCtrl::AddTool аналогичной, содержащей флажок TTF_SUBCLASS в поле uFlags структуры TOOLINFO, используемой в сообщениях TTM_ADDTOOL. А еще лучше заменить ее двумя функциями - для добавления подсказок ToolTips к дочерним окнам и к прямоугольным областям окна. Функция AddTool предусматривает эти возможности, но синтаксически два этих метода очень отличаются друг от друга.
На лист. 1 и 2 приведен исходный текст для производного от CToolTipCtrl класса, носящего название CToolTipCtrlEx. Производному классу помимо унаследованных от CToolTipCtrl:AddWindow принадлежат две функции: для назначения подсказки ToolTip дочернему окну и AddRectangle, которая выполняет то же самое для прямоугольной области окна. Чтобы облегчить задачу назначения подсказки, в обеих функциях используется флажок TTF_SUBCLASS. Обозначим объект CToolTipCtrlEx как m_tooltipCtrl, тогда фрагмент для присвоения подсказки ToolTip кнопочному переключателю с идентификатором IDC_BUTTON выглядит довольно элементарно:
m_tooltipCtrl. AddWindow (GetDlgItem (IDC_BUTTON),
"Введите сюда текст подсказки!");
Лист. 1. Заголовочный файл класса CToolTipCtrlEx.
// ToolTip. h: заголовочный файл
//
////////////////////////////////////////////////////////////
//Окно CToolTipCtrlEx
class AFX_EXT_CLASS CToolTipCtrlEx : public CToolTipCtrl
{
// Конструктор
public:
BOOL AddRectangle (CWnd* pWnd, LPCTSTR pszText, LPCRECT pRect, UINT nIDTool);
BOOL AddWindow (CWnd* pWnd, LPCTSTR pszText);
CToolTipCtrlEx();
//Атрибуты
public:
//Операции
public:
//Переопределения
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CToolTipCtrlEx)
//}}AFX_VIRTUAL
//Реализация
public:
virtual ~CToolTipCtrlEx();
// Сгенерированные функции message map
protected:
//{{AFX_MSG(CToolTipCtrlEx)
// Обратите внимание - "мастер" ClassWizard добавит
// макрокоманды
// remove member functions here,
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
Лист. 2. cpp-файл для класса CToolTipCtrlEx.
// ToolTip. cpp : файл реализации
//
#include "stdafx. h"
#include "stdafx. h"
#include "ToolTip. h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////////////////
// CToolTipCtrlEx
CToolTipCtrlEx::CToolTipCtrlEx()
{
}
CToolTipCtrlEx::~CToolTipCtrlEx()
{
}
BEGIN_MESSAGE_MAP(CToolTipCtrlEx, CToolTipCtrl)
//{{AFX_MSG_MAP(CToolTipCtrlEx)
// NOTE - the ClassWizard will add remove mapping
// macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////
// Обработчики сообщений CToolTipCtrlEx
BOOL CToolTipCtrlEx::AddWindow (CWnd* pWnd, LPCTSTR pszText)
{
TOOLINFO ti;
ti, cbSize = sizeof (TOOLINFO);
ti. uFlags = TTF_IDISHWND | TTF_SUBCLASS;
ti. hwnd = pWnd->GetParent ()->GetSafeHwnd ();
ti. uId = (UINT) pWnd->GetSafeHwnd ();
ti. hinst = AfxGetInstanceHandle ();
ti. lpszText = (LPSTR) pszText;
return (BOOL) SendMessage (TTM_ADDTOOL, 0, (LPARAM) &ti);
}
BOOL CToolCtrlEx::AddRectangle (CWnd* pWnd, LPCTSTR pszText, LPCRECT pRect, UINT nIDTool)
{
TOOLINFO ti;
ti. cbSize = sizeof (TOOLINFO);
ti. uFlags = TTF_SUBCLASS;
ti. hwnd = pWnd->GetSafeHwnd ();
ti. uId = nIDTool;
ti. hinst = AfxGetInstanceHandle ();
ti. lpszText = (LPSTR) pszText;
::CopyRect (&ti. rect, pRect);
return (BOOL) SendMessage (TTM_ADDTOOL, 0, (LPARAM) &ti);
}
Как оформить класс CToolTipCtrlEx в виде DLL-модуля:
1. Запуcтите Visual C++, создайте новый проект, выбрав пункт New (новый) в меню File, и щелкните дважды на команде Project Workspace (рабочая область проекта). В поле Name (имя) рабочей области нового проекта New Project Workspace наберите символы "MfcExt" (без кавычек). В окне Type (тип) выберите "мастера" MFC AppWizard(dll), затем щелкните на кнопке Create (создать).
2. В окне Step 1 "мастера" AppWizard в ответ на вопрос: "What type of DLL would you like to create?" ("Какого типа DLL-модуль вы хотите сформировать?") - выберите "MFC Extension DLL (using shared MFC DLL) [DLL-модуль расширения MFC (с использованием разделяемого модуля DLL MFC).] Щелкните на кнопке Finish (завершить) и на кнопке OK, чтобы сгенерировать исходный текст DLL-модуля. Обратите внимание на заключенную в скобки фразу "using shared MFC DLL", следующую за словами "MFC Extension DLL". Если вы составляете DLL-модуль расширения MFC, нет необходимости реализовывать возможность постоянной привязки к MFC. DLL-модуль должен быть связан с библиотеками MFC динамически.
3. Обратитесь к "мастеру" классов ClassWizard и щелкните на кнопке Add Class (добавить класс). Выберите New, чтобы открыть окно Create New Class (создать новый класс). В этом окне выберите CToolTipCtrl в панели "Base class" (базовый класс) и тип "CToolTipCtrlEx" в панели "Name". Щелкните на кнопке Change (изменить), чтобы изменить имена файлов Tooltip. h и Tooltip. cpp. (Особой надобности в подобных изменениях нет, но я все же выполняю этот шаг, чтобы избавиться от длинных имен файлов.) Отмените выбор в окне "Add to Component Gallery" ("Добавить к галерее компонентов"), чтобы сэкономить пространство на диске. Щелкните на команде Create, чтобы сообщить "мастеру" классов ClassWizard о необходимости породить новый класс, и на кнопке OK, чтобы завершить работу этого "мастера".
4. Добавьте к классу CToolTipCtrlEx принадлежащие функции AddWindow и AddRectangle. Позаботьтесь о том, чтобы обе функции были объявлены как public (общедоступные), поскольку обращения к ним будут происходить за пределами класса CToolTipCtrlEx. В Visual C++ есть простой способ добавления функции, принадлежащей классу, - щелкнуть правой клавишей мыши на имени класса в окне ClassView и выбрать в контекстном меню команду Add Function (добавить функцию).
5. В окне ClassView щелкните дважды на CToolTipCtrlEx, чтобы открыть заголовочный файл этого класса. Добавьте AFX_EXT_CLASS к описанию класса справа от ключевого слова class (см. лист. 1).
6. Создайте свой проект. В результате вы получите два очень важных файла: собственно DLL-модуль (Mfcext. dll) и библиотеку импорта DLL-модуля (Mfcext. lib). Библиотека импорта содержит в основном список имен экспортируемых функций или, как в нашем случае, перечень экспортируемых классов Cи++. Благодаря связи с библиотекой импорта программа может работать с классами, экспортируемыми из DLL-модулей расширения MFC, так, словно библиотека, содержащая эти классы, связана статически. Кроме этого, связь с библиотекой Mfcext. lib служит для Windows признаком того, что для выполнения конкретной программы необходим файл Mfcext. dll.
ОТЧЕТ
Лист. 1. Заголовочный файл класса CToolTipCtrlEx.
class AFX_EXT_CLASS CToolTipCtrlEx : public CToolTipCtrl {
// Конструктор
public:
BOOL AddRectangle (CWnd* pWnd, LPCTSTR pszText, LPCRECT pRect, UINT nIDTool);
BOOL AddWindow (CWnd* pWnd, LPCTSTR pszText); CToolTipCtrlEx();
//Атрибуты
public:
//Операции
public:
//Переопределения
//{{AFX_VIRTUAL(CToolTipCtrlEx)
//}}AFX_VIRTUAL
//Реализация
public: virtual ~CToolTipCtrlEx();
// Сгенерированные функции message map protected:
//{{AFX_MSG(CToolTipCtrlEx)
// Обратите внимание - "мастер" ClassWizard добавит
// макрокоманды
// remove member functions here,
//}}AFX_MSG
DECLARE_MESSAGE_MAP() };
Лист. 2. cpp-файл для класса CToolTipCtrlEx.
#include "stdafx. h"
#include "stdafx. h"
#include "ToolTipCtrlExt. h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////////////////
// CToolTipCtrlEx
CToolTipCtrlEx::CToolTipCtrlEx() {}
CToolTipCtrlEx::~CToolTipCtrlEx() { }
BEGIN_MESSAGE_MAP(CToolTipCtrlEx, CToolTipCtrl)
//{{AFX_MSG_MAP(CToolTipCtrlEx)
// NOTE - the ClassWizard will add remove mapping
// macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////
// Обработчики сообщений CToolTipCtrlEx
BOOL CToolTipCtrlEx::AddWindow (CWnd* pWnd, LPCTSTR pszText)
{ TOOLINFO ti;
ti. cbSize = sizeof (TOOLINFO);
ti. uFlags = TTF_IDISHWND | TTF_SUBCLASS;
ti. hwnd = pWnd->GetParent ()->GetSafeHwnd ();
ti. uId = (UINT_PTR)pWnd->GetSafeHwnd ();
ti. hinst = AfxGetInstanceHandle ();
ti. lpszText = (LPWSTR) pszText;
return (BOOL) SendMessage (TTM_ADDTOOL, 0, (LPARAM) &ti);
}
BOOL CToolTipCtrlEx::AddRectangle (CWnd* pWnd, LPCTSTR pszText, LPCRECT pRect, UINT nIDTool)
{ TOOLINFO ti;
ti. cbSize = sizeof (TOOLINFO);
ti. uFlags = TTF_SUBCLASS;
ti. hwnd = pWnd->GetSafeHwnd ();
ti. uId = nIDTool;
ti. hinst = AfxGetInstanceHandle ();
ti. lpszText = (LPWSTR) pszText;
::CopyRect (&ti. rect, pRect);
return (BOOL) SendMessage (TTM_ADDTOOL, 0, (LPARAM) &ti);
}
Задание 2. Создать DLL и подключить ее с библиотекой импорта и без библиотеки импорта.
ОТЧЕТ
Заголовочный файл (DLLTEST. H)
// This class is exported from the DllTest. dll
class DLLTEST_API CDllTest {
public:
CDllTest(void);
// TODO: add your methods here.
};
extern DLLTEST_API int nDllTest;
DLLTEST_API int fnDllTest(void);
#ifndef _DLLTEST_H_
#define _DLLTEST_H_
#include <iostream>
#include <stdio. h>
#include <windows. h>
extern "C" __declspec(dllexport) void NumberList();
extern "C" __declspec(dllexport) void LetterList();
#endif
Код библиотеки (DLLTEST. CPP)
#include "stdafx. h"
#include "DllTest. h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
}
return nRetCode;
}
*/
#include "stdafx. h"
#include "dlltest. h"
#define MAXMODULE 50
char module[MAXMODULE];
using namespace std;
extern "C" __declspec(dllexport) void NumberList()
{
GetModuleFileName(NULL, (LPTSTR)module, MAXMODULE);
cout << "\n\nThis function was called from "
<< module
<< endl << endl;
cout << "NumberList(): ";
for(int i=0; i<10; i++)
{
cout << i << " ";
}
cout << endl << endl;
}
extern "C" __declspec(dllexport) void LetterList()
{
GetModuleFileName(NULL, (LPTSTR)module, MAXMODULE);
cout << "\n\nThis function was called from "
<< module
<< endl << endl;
cout << "LetterList(): ";
for(int i=0; i<26; i++)
{
cout << char(97 + i) << " ";
}
cout << endl << endl;
}
Исходный файл приложения, использующего библиотеку DLL (Test1.EXE)
#include <conio. h>
#include "test1.h"
void main()
{
NumberList();
LetterList();
getch();
}
Работа программы



