- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
#import "..ServerDebugPointServer.tlb" no_namespace named_guids
Для того, чтобы компилятор смог найти TLB-файл нашего сервера по указанному пути, папки с проектами клиента и сервера должны находиться в общем каталоге. Если вы правильно указывали пути для проектов при их создании, как я просил, то все будет нормально.
Теперь давайте добавим в класс CPointClientDlg (файл PointClientDlg.h) две приватные переменные:
private:
IMyInterfacePtr m_MyInterface;
DWORD m_dwCookie;
Первая из них есть указатель на интерфейс нашего COM-сервера, который мы создавали несколько раньше. Тип IMyInterfacePtr любезно предоставила нам директива #import, после того как мы подключили файл PointServer.tlb. С помощью данного импорта мы приобрели много полезной информации о нашем сервере. Она находится в файлах PointServer.tlh и PointServer.tli, в том числе и определение IMyInterfacePtr. Изучите эти файлы на досуге и, возможно, вы откроете для себя что-то новое.
Вторая переменная (m_dwCookie) есть уникальный идентификатор, который вернет нам функция AfxConnectionAdvise. Помните, я уже рассказывал о механизме подписки клиентов на сообщения от сервера. Тогда мы говорили о функциях Advise и Unadvise интерфейса IConnectionPoint. Здесь же мы будем использовать аналоги этих функций — AfxConnectionAdvise и AfxConnectionUnadvise, предоставляемые библиотекой MFC. Так вот, m_dwCookie — это идентификатор нашей подписки, который вернет нам сервер в случае успешной регистрации нашего соединения. Зачем он нам нужен? Ну, хотя бы для того, чтобы отдать его серверу, когда мы пожелаем отписаться от принятия сообщений, ведь должен же сервер знать, кого он будет удалять из своего списка. Другими словами, m_dwCookie — это аналог того номерка, что дают вам злые тети в раздевалках, если вы сдаете одежду, при походах в театр, библиотеку и т.д. Сохраните сделанные нами изменения и закройте этот файл.
Теперь займемся файлом реализации класса CPointClientDlg. Для этого откройте файл PointClientDlg.cpp, найдите функцию OnInitDialog и строку в ней
// TODO: Add extra initialization here
Вот вместо этого напоминания мы сейчас и напишем наш код. Здесь будет находиться код загрузки COM-сервера, а также функция подписки на его события. Итак, вместо комментариев, указанных мастером вставьте следующие строки:
EnableAutomation();
UUID uuid;
m_MyInterface = NULL;
uuid = __uuidof(MyInterface);
m_MyInterface.CreateInstance(uuid);
m_dwCookie = 0;
BOOL Ret = AfxConnectionAdvise(
m_MyInterface,
DIID_IFireClassEvents,
this->GetIDispatch(FALSE), // get the IDispatch assocaiated with Mainframe...
FALSE, // donod addref
&m_dwCookie); // cookie to break connection later...
С помощью __uuidof мы получим UUID интерфейса IMyInterface, который затем подставим в функцию CreateInstance. Таким образом, мы вызовем загрузку нашего COM-сервера.
После того, как функция CreateInstance будет успешно выполнена, мы подпишемся на сообщения от интерфейса IFireClassEvents с помощью функции AfxConnectionAdvise. В случае корректного завершения которой мы получим наш идентификатор – m_dwCookie. Приведенный код не содержит механизма обработки возможных ошибок, чтобы не загромождать главную идею, которую мы сейчас рассматриваем. В случае необходимости вы можете добавить его сами. Ну вот, к тому моменту, как мы увидим на экране диалог нашего клиента, COM-сервер будет уже загружен и готов посылать нам событие, что мы реализовали в его коде.
Сразу же добавим код отписки от событий, который вставим в обработчик нажатия кнопки ОК:
void CPointClientDlg::OnOK() {
if (m_MyInterface) {
AfxConnectionUnadvise(m_MyInterface, DIID_IFireClassEvents, this->GetIDispatch(FALSE), FALSE, m_dwCookie);
m_MyInterface = NULL;
}
CDialog::OnOK();
}
Здесь все предельно ясно. Передавая нашу «куку» (m_dmCookie) функции AfxConnectionUnadvise, мы тем самым отписываемся от рассылки событий. После чего делаем m_MyInterface = NULL, чем вызываем выгрузку COM-сервера.
Последним штрихом добавим код в обработчик второй нашей кнопки:
void CPointClientDlg::OnFireevent() {
m_MyInterface->FireMyEvent();
}
Сохраните все сделанные нами изменения и постройте проект. Если все сделали правильно, то должны были получить 2 сообщения об ошибке, рисунок 11.
Рисунок 11
Все правильно. Для того, чтобы эти функции не вызывали ошибок нужно сделать следующее подключение:
#include <afxctl.h>
Попробуйте снова. Сейчас все должно быть без ошибок.
Устали? Я тоже. Подождите, осталось совсем немного. Сейчас мы реализуем код функции, что будет вызывать у нас сервер, и на этом закончим. Итак, откройте файл PointClientDlg.h и сразу после декларации карты сообщений вставьте ещё несколько определений:
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()
BOOL OnMyEvent();
Таким способом вы объявите две карты: DISPATCH MAP и INTERFACE MAP, которые нам необходимы. А также объявите обработчик OnMyEvent события MyEvent. Сохраните, сделанные изменения и закройте файл.
Теперь откройте файл реализации класса CPointClientDlg, PointClientDlg.cpp, и сразу после окончания реализации карты сообщений вставьте следующий код:
BEGIN_DISPATCH_MAP(CPointClientDlg, CDialog)
DISP_FUNCTION_ID(CPointClientDlg, "MyEvent",1, OnMyEvent, VT_BOOL, VTS_NONE)
END_DISPATCH_MAP( )
BEGIN_INTERFACE_MAP(CPointClientDlg, CDialog)
INTERFACE_PART(CPointClientDlg, DIID_IFireClassEvents, Dispatch)
END_INTERFACE_MAP()
BOOL CPointClientDlg::OnMyEvent() {
AfxMessageBox("Event!!!!!!!!");
return TRUE;
}
Что же это означает?
Во-первых, между макросами BEGIN_DISPATCH_MAP и END_DISPATCH_MAP, с помощью DISP_FUNCTION_ID по номеру метода (1 — см. ODL-файл сервера) мы указываем имя события (MyEvent), его обработчик (OnMyEvent), тип возвращаемого значения (VT_BOOL), а также тип аргументов (VTS_NONE — в данном случае их нет).
Далее идет реализация интерфейсной карты и реализация функции обработчика события OnMyEvent.
На этом, пожалуй, все. Сохраните файл, постройте проект и запустите на выполнение нашего клиента. Если вы все делали правильно, то по нажатию на кнопку "Fire Event", должны получить результат как на рисунке 12.
Рисунок 12
На этом я закончу. Надеюсь, что этот материал кому-то окажет помощь в трудную минуту.
ВОПРОС-ОТВЕТ
Как узнать имя exe-файла выполняемой программы?
Автор: Артур Вартанов
Функция GetModuleFileName возвращает полный путь и имя исполняемого файла. Пример ее использования смотри ниже.
TCHAR FileName[MAX_PATH + 1]; // буфер для имени файла
GetModuleFileName(NULL, FileName, MAX_PATH + 1);
Первый параметр функции GetModuleFileName – дескриптор модуля, для которого требуется получить имя. Если в качестве первого параметра указан hInstance программы или NULL, возвращается имя выполняемой программы. Если же указать дескриптор загруженного модля (DLL), который возвращается функциями LoadLibrary, LoadLibraryEx или GetModuleHandle, возвращается имя этой DLL. Кроме функции GetModuleFileName, существует функция GetModuleFileNameEx, позволяющая получить имя модуля, загруженного в адресное пространство другого процесса.
Это все на сегодня. Пока!
Алекс Jenter [email protected] Красноярск, 2001. Рассылка является частью проекта RSDN.Программирование на Visual C++
Выпуск №50 от 15 июля 2001 г.
Приветствую вас!
СТАТЬЯ Отчёты Crystal Reports для Visual C++ 6 Автор: Илья ГуняНедавно я начал писать один небольшой проект на VC с отчетом Crystal Reports 8 и столкнулся со следующей проблемой: я не знал, как написать отчет. После поиска материалов на эту тему в интернете, у меня сложилось впечатление, что перед разработчиками на VC не стоит проблема создания отчетов. На CodeGuru в разделе Databases я не нашел ни одного материала на эту тему. Пришлось копать эту тему самому. К сожалению, у меня оказался только один пример, в котором довольно сложный отчет полностью создаётся в run-time без использования редактора отчетов. Это автоматически означало, что мне нужно будет изучить несколько десятков, а то и сотен килобайт текста, прежде чем я выдам первый отчет. Времени на это у меня не было. Поэтому для создания отчета я воспользовался следующей технологией, которая и описывается ниже.
Для выполнения этого проекта необходимо:
• Visual C++ 6
• Crystal Reports 8
Приступим.
Для начала, создадим наш отчет. Запускаем Crystal Report Designer. Создаем blank report. Добавляем ODBC connection, указывающее, на пример, на БД pubs на вашем SQL сервере, или на какую-нибудь таблицу в mdb-файле. Выбираем таблицу pubs.dbo.authors, давим add кнопку, закрываем окно. В появившемся окне дизайнера отчетов перетаскиваем в область Details нужные поля: au_id, au_fname, au_lname. Сохраняем отчёт.
Создаём простой Dialog-based проект со всеми настройками по умолчанию. В меню Projects->Add to project->Components and controls добавляем Crystal Report Viewer Control. В окне Confirm classes давим OK. Закрываем окно Components and controls. Добавляем Crystal Report Viewer Control на диалог. В окне ClassWizard для диалога добавляем обработчик WM_SHOWWINDOW. At the Member variables tab добавляем переменную m_CRView1. В начало файла SampRepDlg.cpp добавляем строки