Программирование >>  Арифметические и логические операции 

1 ... 31 32 33 [ 34 ] 35 36 37 ... 53


Description : %s\n Source : %s\n , er.Error(),

(LPCTSTR) bstr t(er.ErrorMessage()),

(LPCTSTR) bstr t(er.Description()),

(LPCTSTR) bstr t(er.Source()));

CharToOem(buf,buf); только для консольных приложений printf(buf);

::CoUninitialize();

AciveX Control

Для этого примера нам понадобится любое оконное приложение.

ActiveX Controlы вставляются в диалог обычно через Components and Controls Gallery: Menu * Project Add To Project * Components and Controls-Registered ActiveX Controls.

Нам в качестве примера вполне подойдёт Microsoft FlexGrid Control. Нажмите кнопку Insert для добавления его в проект, в появившемся окне Confirm Classes оставьте галочку только возле элемента CMSFlexGrid и смело жмите OK. В результате будут сформированы два файла msflexgrid.h и msflexgrid.cpp, большую часть содержимого которых нам придётся удалить. После всех изменений эти файлы будут иметь следующий вид:

msflexgrid.h

msflexgrid.h

#ifndef MSFLEXGRID H #define MSFLEXGRID H

#if MSC VER > 1000 #pragma once

#endif MSC VER > 1000

#pragma warning(disable:4146) #import <MSFLXGRD.OCX>

class CMSFlexGrid : public CWnd

protected:

DECLARE DYNCREATE(CMSFlexGrid) public:

MSFlexGridLib::IMSFlexGridPtr I; доступ к интерфейсу void PreSubclassWindow (); инициализация I

{{AFX INSERT LOCATION}}

#endif

msflexgrid.cpp

msflexgrid.cpp

#include stdafx.h #include msflexgrid.h

IMPLEMENT DYNCREATE(CMSFlexGrid, CWnd)

void CMSFlexGrid::PreSubclassWindow () CWnd::PreSubclassWindow();

MSFlexGridLib::IMSFlexGrid *pInterface = NULL;

if (SUCCEEDED(GetControlUnknown()->QueryInterface(I.GetIID(),

(void**)&pInterface))) { ASSERT(pInterface != NULL); I.Attach(pInterface);

Теперь вставим элемент в любой диалог, например CAboutDlg. В диалог добавим переменную связанную с классом CMSFlexGrid и метод OnInitDialog, текст которого приведён ниже. При вызове диалога в наш FlexGrid будут добавлены два элемента:

BOOL CAboutDlg::OnInitDialog()

CDialog::OnInitDialog();

m grid.I->AddItem( 12345 ); m grid.I->AddItem( 54321 );

return TRUE;



В заключении, позволим ещё несколько замечаний.

Всегда внимательно изучайте файлы *.tlh. Отчасти они могут заменить документацию, а если её нет, то это единственный источник информации (кроме, конечно, OLE/COM Object Viewer).

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

book->Worksheets->Item[1L]->Range[ B2 ]->FormulaR1C1 = Строка 1 ;

book->Worksheets->Item[1L]->Range[ C2 ]->FormulaR1C1 = 12345L;

Но в данном случае вы получите неоправданное замедление из-за лишнего межзадачного взаимодействия, а в случае DCOM - сетевого взаимодействия. Лучше написать так:

WorksheetPtr sheet = book->Worksheets->Item[1L]; sheet->Range[ B2 ]->FormulaR1C1 = Строка 1 ; sheet->Range[ C2 ]->FormulaR1C1 = 12345;

При работе с MS Office максимально используйте возможности VBA для подготовки и тестирования вашего кода.

Будьте внимательны с версиями библиотек типов. К примеру, в MS Word 2000 появилась новая версия метода Run. Старая тоже осталась, но она имеет теперь название RunOld. Если вы используете MS Word 2000 и вызываете метод Run, то забудьте о совместимости с MS Word 97 - метода с таким ID в MS Word 97 просто нет. Используйте вызов RunOld и проблем не будет, хотя если очень хочется можно всегда проверить номер версии MS Word.

Бывают глюки. Сразу заметим, что это не связано с самой директивой #import. Например, при использовании класса COleDispatchDriver с MSADODC.OCX всё прекрасно работало, а после того как стали использовать директиву #import, свойство ConnectionString отказалось возвращать значение. Дело в том, что директива #import генерирует обёртку, используя dual-интерфейс объекта, а класс COleDispatchDriver вызывает ConnectionString через IDispatch::Invoke. Ошибка, видимо, в реализации самого MSADODC.OCX. После изменения кода вызова свойства всё заработало:

inline bstr t IAdodc::GetConnectionString () { BSTR result;

HRESULT hr = com dispatch propget(this,0x01,VT BSTR,& result); HRESULT hr = get ConnectionString(& result); if (FAILED( hr)) com issue errorex( hr, this, uuidof(this)); return bstr t( result, false);

В результате раскрутки библиотек типов MS Office, компилятор нагенерирует вам в выходной каталог проекта около 12 Mb исходников. Всё это он потом, естественно, будет компилировать. Если вы не являетесь счастливым обладателем PIII, то наверняка заметите некоторые тормоза. В таких случаях надо стараться выносить в отдельный файл всю работу, связанную с подобными библиотеками типов. Кроме того, компилятор может генерировать обёртки классов каждый раз после внесения изменений в файл, в который включена директива #import. Представьте, что будет, если после каждого нажатия клавиши будут заново генерироваться все 12 Mb? Лучше вынести объявление директивы #import в отдельный файл и подключать его через #include.

Удачи в бою.

Глава 21.

Создание системных ловушек Windows на Borland C++ Builder

Для начала определим, что именно мы хотим сделать.

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

Предполагается, что такая программа должна иметь небольшой размер. Поэтому будем писать её с использованием только WIN API.

Понятие ловушки

Ловушка (hook) - это механизм, который позволяет производить мониторинг сообщений системы и обрабатывать их до того как они достигнут целевой оконной процедуры.

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

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

♦ Написание DLL c функциями ловушки (их будет две: одна для клавиатуры, другая для мыши).



♦ Написание приложения, которое установит ловушку.

♦ Написание DLL.

♦ Создание пустой библиотеки.

С++ Builder имеет встроенный мастер по созданию DLL. Используем его, чтобы создать пустую библиотеку. Для этого надо выбрать пункт меню File * New: В появившемся окне надо выбрать DLL Wizard и нажать кнопку ОК . В новом диалоге в разделе Source Type следует оставить значение по умолчанию - C++ . Во втором разделе надо снять все флажки. После нажатия кнопки Ок пустая библиотека будет создана.

Глобальные переменные и функция входа (DllEntryPoint)

Надо определить некоторые глобальные переменные, которые понадобятся в дальнейшем.

#define UP 1 Состояния клавиш #define DOWN 2 #define RESET 3

int iAltKey; Здесь хранится состояние клавиш int iCtrlKey; int iShiftKey;

int KEYBLAY; Тип переключения языка bool bSCRSAVEACTIVE; Установлен ли ScreenSaver MOUSEHOOKSTRUCT* psMouseHook; Для анализа сообщений от мыши В функции DllEntryPoint надо написать код, подобный нижеприведённому:

if(reason==DLL PROCESS ATTACH) Проецируем на адр. простр.

HKEY pOpenKey;

char* cResult= ; Узнаём как перекл. раскладка

long lSize=2; KEYBLAY=3;

if(RegOpenKey(HKEY USERS, .Default\\keyboard layout\\toggle , &pOpenKey)==ERROR SUCCESS)

RegQueryValue(pOpenKey, ,cResult,&lSize);

if(strcmp(cResult, 1 )==0) KEYBLAY=1; Alt+Shift if(strcmp(cResult, 2 )==0)

KEYBLAY=2; Ctrl+Shift

RegCloseKey(pOpenKey);

else

MessageBox(0, Не могу получить данные о способе переключения раскладки клавиатуры , Внимание! ,MB ICONERROR);

------------- Есть ли активный хранитель экрана

if(!SystemParametersInfo(SPI GETSCREENSAVEACTIVE,0,&bSCRSAVEACTIVE

,0))

MessageBox(0, Не могу получить данные об установленном хранителе экрана , Внимание! ,MB ICONERROR);

return 1;

Этот код позволяет узнать способ переключения языка и установить факт наличия активного хранителя экрана. Обратите внимание на то, что этот код выполняется только когда библиотека проецируется на адресное пространство процесса - проверяется условие (reason==DLL PROCESS ATTACH).

Функция ловушки клавиатуры

Функция ловушки в общем виде имеет следующий синтаксис:

LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam),

где:

♦ HookProc - имя функции;

♦ nCode - код ловушки, его конкретные значения определяются типом ловушки;

♦ wParam, lParam - параметры с информацией о сообщении.

В случае нашей задачи функция должна определять состояние клавиш Alt, Ctrl и Shift (нажаты или отпущены). Информация об этом берётся из параметров wParam и lParam. После определения состояния клавиш надо сравнить его со способом переключения языка (определяется в функции входа). Если текущая комбинация клавиш способна переключить язык, то надо выдать звуковой сигнал.



1 ... 31 32 33 [ 34 ] 35 36 37 ... 53

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика