|
Программирование >> Арифметические и логические операции
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. После определения состояния клавиш надо сравнить его со способом переключения языка (определяется в функции входа). Если текущая комбинация клавиш способна переключить язык, то надо выдать звуковой сигнал.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |