Электронная библиотека » Александр Чиртик » » онлайн чтение - страница 18


  • Текст добавлен: 10 ноября 2013, 00:08


Автор книги: Александр Чиртик


Жанр: Программирование, Компьютеры


сообщить о неприемлемом содержимом

Текущая страница: 18 (всего у книги 24 страниц) [доступный отрывок для чтения: 8 страниц]

Шрифт:
- 100% +
Трюки в Microsoft Excel

Не менее популярным и функциональным приложением из пакета Microsoft Office является Microsoft Excel. Это программа предназначена для работы с электронными таблицами. Как и Microsoft Word, Microsoft Excel также обладает возможностью создания и редактирования документов (в данном случае таблиц) посредством использования технологии COM. Преимущества использования Microsoft Excel очевидны, так как она предоставляет широкий спектр возможностей по построению диаграмм, графиков, произведению различных расчетов и пр. Поэтому в качестве примера будет создано приложение, выполняющее запуск Microsoft Excel, добавление новой книги, создание листа и помещение в его ячейки текста и формул.

Как и в случае с Microsoft Word, будет использоваться объект типа OleVariant. Однако методы и свойства COM-сервера поменяются. Рассмотрим исходный текст приложения, предназначенного для выполнения несложных операций с сервером Microsoft Excel (листинг 9.8).

Листинг 9.8. Работа с Microsoft Excel

unit COMinExcel;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs,

//Включаем модуль работы с COM-объектами

ComObj;

type

TFormCOMExcel = class(TForm)

//Процедура, вызываемая при создании формы

procedureeeFormCreate (Sender: TObject);

//Процедура, вызываемая при завершении работы приложения

procedure FormDestroy(Sender: TObject);

private

{Private declarations}

public

{Public declarations}

end;

var

FormCOMExcel: TFormCOMExcel;

//Объявление объекта OleVariant с именем Microsoft Excel

Excel: OleVariant;

implementation

{$R *.dfm}

procedure TFormCOMExcel.FormCreate(Sender: TObject);

begin

//Инициализируем объект

Excel:= CreateOleObject('Excel.Application');

//Устанавливаем видимым окно приложения Microsoft Excel

Excel.Visible:= true;

//Добавляем новую книгу

Excel.Application.Workbooks.Add;

//Вводим текст в ячейку с индексом E5

Excel.Application.Worksheets.Item['Лист 1'].

Cells.Item[5,5].FormulaR1C1:= '! ТЕКСТ !';

//Задаем характеристики ишрифта

Excel.Application.Worksheets.Item[' Лист 1'].

Cells.Item[1,1].Font.Bold:= true;

//В ячейку с индексом A1 записываем формулу

Excel.Application.Worksheets.Item['Лист 1'].

Cells.Item[1,1].FormulaR1C1:= '=18*2';

end;

procedure TFormCOMExcel.FormDestroy(Sender: TObject);

begin

//Закрываем приложение Microsoft Excel

Excel.Quit;

end;

end.


Программа, представленная в данном листинге, демонстрирует основы удаленного управления приложением Microsoft Excel. Запуск Microsoft Excel и заполнение ячеек новой таблицы происходит в функции FormCreate. Во время создания главной формы приложения-примера на экране появляется окно программы Microsoft Excel с числом в ячейке А1 и текстом в ячейке Е5. Хотя в ячейку А1 было записано выражение =18*2, на экране в этой ячейке отображается число 3 6, так как Microsoft Excel автоматически преобразует выражения в ячейках.

Глава 10
Окна других приложений

• Ловушки Windows

• Программа «Оконный шпион»


В данной главе будут использованы сведения, приведенные в предыдущих главах (а точнее, в главах 1, 2 и 8), для построения программы, позволяющей проводить различные операции с окнами приложений. Вы также дополнительно познакомитесь с техникой применения ловушек (hook) в Windows и увидите пример реального использования проецирования файла в память для обмена данными между несколькими приложениями. Причем второе в примере обусловлено особенностью работы ловушек, следящих за работой других приложений. Вы также узнаете, как перечислять все открытые окна и, соответственно, получать к ним доступ. Но обо всем по порядку.

Ловушки Windows

Из материала предыдущих глав вам должен быть понятен или, по крайней мере, известен механизм, используемый Windows для управления окнами приложений, – сообщения. Вероятно, большая мощь этого механизма и, в то же время, его уязвимость заключаются в возможности отсылать сообщения любым окнам (окнам одного процесса или окнам других процессов).

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

Здесь будут рассмотрены некоторые наиболее простые виды ловушек, перехватывающих сообщения окон. По глобальности действий рассмотренные ловушки являются устанавливаемыми на отдельный поток – такой подход безопаснее для системы, если в функции-ловушке возникнет ошибка.

Начинается создание ловушки с написания собственно функции-ловушки, имеющей следующий прототип:


function HookProc(code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT stdcall;


О параметре code можно сказать, что он используется для обозначения тех случаев, когда функция ловушки должна вызвать специальную API-функцию CallNextHookEx и вернуть значение, возвращенное этой API-функцией. Назначения параметров wParam и lParam этой функции сильно зависят от того, для реакции на какое именно событие предназначена ловушка.

Для регистрации ловушки используется API-функция SetWindowsHookEx, имеющая следующий прототип:


function SetWindowsHookEx(idHook: Integer; //Тип ловушки

lpfn: TFNHookProc; //Адрес функции-ловушки

hmod: HINST; //Используемый модуль, в котором

//расположена функция ловушки

dwThreadId: DWORD //Идентификатор потока, для

//которого создается ловушка

): HHOOK; stdcall;


Если создание ловушки завершено успешно, функция SetWindowsHookEx возвращает дескриптор новой ловушки (ненулевое значение).

Для удаления ловушки используется функция UnhookWindowsHookEx, принимающая единственный параметр – дескриптор ловушки, возвращенный функцией SetWindowsHookEx. Удалять ловушку нужно обязательно, поэтому, по крайней мере при закрытии приложения, не следует забывать вызывать функцию UnhookWindowsHookEx.

Теперь несколько слов о функции CallNextHookEx. Ее объявление выглядит следующим образом:


function CallNextHookEx(hhk: HHOOK; nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;


В чем важность этой функции? Она предназначена для продолжения передачи сообщения по цепочке ловушек (ведь одновременно несколько приложений могут создавать ловушки). Вызов этой функции настоятельно рекомендуется выполнять в любом случае (независимо от значения параметра code функции-ловушки), если, правда, целью не является блокирование других ловушек.

Виды ловушек

Ниже представлен список некоторых простых типов ловушек, а именно констант из модуля Windows, обозначающих эти типы и передаваемых в функцию SetWindowsHookEx:

• WH_CALLWNDPROC – функция ловушки вызывается каждый раз до вызова функции обработки сообщений окон, созданных наблюдаемым потоком;

• WH_CALLWNDPROCRET – вызывается каждый раз при возврате из функции обработки сообщений окон наблюдаемого потока;

• WH_KEYBOARD – функция ловушки вызывается перед обработкой сообщений WM_KEYDOWN и WM_KEYUP оконной функцией наблюдаемого потока;

• WH_MOUSE – вызывается перед обработкой оконной функцией наблюдаемого потока сообщений от манипулятора «мышь».

Значения параметров lParam и wParam функции-ловушки в каждом из перечисленных случаев подробно рассмотрены ниже.

Перехват вызова оконной функции

Для WH_CALLWNDPROC, которая, кстати, используется в рассматриваемом далее приложении, два последних параметра функции-ловушки имеют следующие значения:

• wParam – равен нулю, если сообщение послано в окно тем же потоком, в котором исполняется функция ловушки, и не равен нулю, если сообщение послано другим потоком;

• lParam – указатель на структуру TCWPStruct, содержащую информацию о сообщении, которое передано окну (и будет передано в оконную функцию после возврата из функции-ловушки).

Объявление структуры TCWPStruct с описанием полей выглядит следующим образом:


type TCWPStruct = packed record

lParam: LPARAM; //Параметр трсообщения

wParam: WPARAM; //Параметр сообщения

message: UINT; //Код сообщения

hwnd: HWND; //Окно, которому адресовано сообщение

end;


Ниже приведен пример преобразования параметра lParam функции-ловушки к указателю на структуру с последующей проверкой кода сообщения (фрагмент программы):


var hook_data: hook_data: ^TCWPStruct;

begin

hook_data:= Pointer(lParam);

if hook_data^.message = WM_SIZE then

begin

//Реагируем на изменение размера окна

end;

end


Получение доступа к данным, передаваемым в остальные функции-ловушки (а именно несложное преобразование типов у операции с указателем), выполняется аналогичным образом, поэтому более демонстрироваться не будет.

Перехват возврата из оконной процедуры

Для WH_CALLWNDPROCRET значения параметров wParam и lParam функции-ловушки следующие:

• wParam – равен нулю, если сообщение послано другим процессом, и не равен нулю в противном случае;

• lParam – указатель на структуру TCWPRetStruct, содержащую информацию о сообщении, которое передано окну (и было передано в оконную функцию до вызова функии-ловушки).

Объявление структуры TCWPRetStruct выглядит следующим образом:


type TCWPRetStruct = packed record

lResult: LRESULT; //Значение, возвращенное оконной функцией

lParam: LPARAM; //Параметр сообщения

wParam: WPARAM; //Параметр сообщения

message: UINT; //Код сообщения

hwnd: HWND; //Дескриптор окна-получателя

end;


Перехват сообщений клавиатурного ввода

Для WH_KEYBOARD значения параметров wParam и lParam функции-ловушки следующие:

• wParam – код нажатой клавиши;

• lParam – первые 16 бит этого параметра означают количество повторений нажатия, старшие же 16 бит используются для дополнительного описания состояния клавиатуры в момент нажатия клавиши.

Параметры wParam и lParam полностью аналогичны параметрам сообщений WM_ KEYDOWN и WM_KEYUP.

Перехват сообщений от мыши

В ловушку WH_MOUSE в параметрах wParam и lParam передаются следующие значения:

• wParam – код сообщения мыши;

• lParam – указатель на структуру TMouseHookStruct.

Объявление структуры TMouseHookStruct выглядит следующим образом:


type TMouseHookStructttt= packeddrecord

pt: TPoint int; //Экранные координаты указателя мыши

hwnd: HWND; //Дескриптор окна-получателя сообщения

wHitTestCode: UINT; //Код, возвращенный оконной функцией в ответ

//на сообщение WM_NCHITTEST

dwExtraInfo: DWORD; //Дополнительные данные

end;


Если вы забыли, какое значение для окна имеет сообщение WM_NCHITTEST, то можете вновь обратиться к гл. 1.

Расположение функции-ловушки и DLL

Теперь немного о расположении функции-ловушки.

Казалось бы, что здесь может быть особенного: написал функцию в модуле, строго соответствующую приведенному ранее прототипу, передал ее адрес в функцию SetWindowsHookEx и используй ловушку. Но не так все просто. Функция ловушки может находиться в исполняемом файле только в том случае, если предполагается использовать ее для перехвата сообщений потока (потоков) того же процесса. Тогда в функцию создания ловушки в качестве параметра HMOD следует передавать нулевое значение.

Если же предполагается слежение за другими приложениями (за потоками других процессов), то функция ловушки должна быть экспортируемой функцией DLL. Тогда в функцию SetWindows HookEx передается дескриптор модуля DLL (похоже, что это адрес в адресном пространстве процесса, куда спроецирован файл DLL). Библиотека (DLL) может загружаться как при запуске приложения (если используется так называемое load-time-связывание), так и динамически с помощью API-функции LoadLibrary:


function LoadLibrary(lpLibFileName: PChar): HMODULE; stdcall;


Функция принимает в качестве параметра путь DLL и возвращает дескриптор загруженного модуля (или 0 в случае ошибки). Если библиотека больше не нужна, то можно вызвать функцию FreeLibrary, передав в качестве единственного параметра возращенный ранее функцией LoadLibrary дескриптор модуля DLL.

Возвращаясь к теме расположения ловушки, следует задасться вопросом, почему используется именно DLL. Чем плохо расположение ловушки в EXE-модуле приложения? Самое время вспомнить о том, что каждый процесс в Windows выполняется в своем собственном адресном пространстве. Поэтому адрес функции в исполняемом файле одного процесса вполне может быть адресом структуры данных где-то внутри другого процесса (рис. 10.1).

Рис. 10.1. Пример адресного пространства разных процессов


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

• проецировать библиотеку с ловушкой в адресное пространство исследуемого процесса;

• однозначно определять положение (адрес) функции-ловушки в адресном пространстве исследуемого процесса.

Описанные выше манипуляции с DLL проиллюстрированы на рис. 10.2 (Процесс 2 на рисунке – процесс, в который внедряется ловушка).

Рис. 10.2. Загрузка DLL с ловушкой в адресное пространство исследуемого процесса


Теперь нет никаких препятствий для вызова функции-ловушки при наблюдении за другим процессом.

Примечание

В каждой библиотеке реализуется функция DllMain, вызываемая (упрощенно) при загрузке или выгрузке библиотеки. Однако при описанном способе подгрузки DLL эта функция не вызывается, что приводит к усложнению кода ловушки, в чем вы сможете вскоре убедиться.

Программа «Оконный шпион»

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

Несмотря на свое «противозаконное» название, рассматриваемая программа может быть весьма полезна при отладке приложений, а не при их взломе и шпионаже (хотя многое зависит от добросовестности лица, использующего программу). В частности, с помощью этой программы была найдена ошибка, закравшаяся в один из примеров, приведенных в гл. 2: из-за неправильной установки стилей при ручном создании главного окна программы не удавалось добиться правильной перерисовки элемента управления «рамка».

Составление списка открытых окон

Список (а точнее, дерево) окон, открытых в момент запуска программы, показан на рис. 10.3.

Рис. 10.3. Дерево открытых окон


Форма, показанная на рис. 10.3, имеет имя frmMain. Элемент управления TreeView имеет имя tree. Часть программы, отвечающая за построение дерева, относительно проста. Она использует вскользь рассмотренный в гл. 2 механизм перечисления окон.

Составление дерева окон начинается с процедуры LoadWindowsTree, которая и запускает перечисление окон верхнего уровня, то есть окон, родителем которых является окно Рабочий стол (листинг 10.1).

Листинг 10.1. Начало составления дерева окон

procedure TfrmMain.LoadWindowsTree();

var

desktop: TTreeNode;

//enInfo: TEnumInfo;

begin

tree.Items.Clear;

//Добавление узла для Рабочего стола

desktop:= tree.Items.Add(t ree.Items.GetFirstNode, 'Рабочий стол');

//Перечисление окон

enInfo.tree:= tree;

enInfo.parent:= desktop;

EnumWindows(Addr(NewWindow), Integer(Addr(enInfo)));

end;


Сразу следует привести объявление структуры, интенсивно используемой (далее это будет видно) при составлении дерева:


Type

TEnumInfo = Record

tree: TTreeView; //Компонент TreeView

parent ntnt: TTreeNode; //Элемент дерева, соответствующий текущему

//окну, дочерние окна которого перечисляются

end;


При нахождении каждого нового окна вызывается функция NewWindow (ее адрес передан в API-функцию EnumWindows). Функция NewWindow (листинг 10.2) решает две задачи. Во-первых, она добавляет в дерево элемент, соответствующий найденному окну. Во-вторых, она запускает поиск дочерних окон относительно найденного окна, что позволяет перечислить все окна (от главной формы приложения до кнопок, надписей и т. д.).

Листинг 10.2. Добавление в дерево элемента и поиск дочерних окон

function NewWindow(wnd: HWND; param: LPARAM):BOOL; stdcall;

var

wndNode, parentNode: TTreeNode;

begin

wndNode:= AddWindowToTree(wnd); //Добавление информации об окне в дерево

//Перечисление дочерних окон

parentNode:= enInfo.parent;

enInfo.parent:= wndNode;

EnumChildWindows(wnd, Addr(NewWindow), param);

enInfo.parent:= parentNode;

//Продолжать перечисление (после перечисления всех дочерних окон)

NewWindow:= True;

end;


Используемая в листинге 10.3 функция AddWindowToTree добавляет элемент, соответствующий найденному окну, в дерево (определяет текст заголовка окна и имя оконного класса).

Листинг 10.3. Добавление элемента, соответствующего окну, в дерево

function AddWindowToTree(wnd: HWND): TTreeNode;

var

caption, classname: String;

text: String;

 node: TTreeNode;

begin

//Получение текста окна

SetLength(caption, SendMessage(wnd, WM_GETTEXTLENGTH, 0, 0) + 1);

SetLength(caption, SendMessage(wnd, WM_GETTEXT, Length(caption),

Integer(PAnsiChar(caption))));

//Имя класса окна

SetLength(classname, 1024);

SetLength(classname, GetClassName(wnd, PAnsiChar(classname), 100));

//Формирование текста для элемента и добавление его в дерево

text:= '"'+ caption + '" '+ classname;

node:= enInfo.tree.Items.AddChild(enInfo.parent, text);

node.Data:= Pointer(wnd); //Не забываем запомнить дексриптор окна

AddWindowToTree:= node;

end;


Вот, собственно, и все, что требуется для построения полного дерева окон, показанного на рис. 10.3.

Получение информации об окне

Следующей функцией оконного шпиона является получение более или менее полной информации об окне, выбранном в дереве. Форма с информацией о выделенном в дереве окне (в данном случае выбрано меню Пуск) показана на рис. 10.4.

Рис. 10.4. Форма свойств окна


По команде меню Правка ► Свойства вызывается метод ShowWindowProp созданного при запуске программы объекта frmWindowProp. Этот метод принимает в качестве параметра дескриптор окна, информацию о котором нужно отобразить (дескриптор был сохранен в поле Data каждого элемента при построении дерева) (листинг 10.4).

Листинг 10.4. Подготовка формы свойств выбранного окна

procedure TfrmWindowProp.ShowWindowProp(window: HWND);

begin

wnd:= window;

LoadWindowInfo();

ShowModal(); //Не забываем показать сами себя

end;


Переменная wnd, в которой сохраняется переданный в ShowWindowProp дескриптор окна, является членом класса TfrmWindowProp. Она нужна для того, чтобы другие методы формы TfrmWindowProp могли получать доступ к дескриптору окна.

Определение заголовка, имени класса, идентификатора окна, а также области экрана, занимаемой окном, выполняется в процедуре LoadWindowlnfo (листинг 10.5).

Листинг 10.5. Определение общей информации об окне

procedure TfrmWindowProp.LoadWindowInfo();

var

rect: TRect;

buffer: String;

begin

//Сбор сведений об окне

//..имя класса

SetLength(buffer, 1024);

SetLength(buffer, GetClassName(wnd, PAnsiChar(buffer), 1024));

txtClassName.Text:= buffer;

//..имя (заголовок) окна

SetLength(buffer, SendMessage(wnd, WM_GETTEXTLENGTH, 0, 0) + 1);

SendMessage(wnd, WM_GETTEXT, Length(buffer),

Integer(PAnsiChar(buffer)));

txtWindowName.Text:= buffer;

//..идентификатор (или дескриптор меню) окна

txtId.Text:= IntToStr(GetWindowLong(wnd, GWL_ID));

//..оконный прямоугольник

GetWindowRect(wnd, rect);

txtWindowRect.Text:=

'('+ IntToStr(rect.Left) + ','+ IntToStr(rect.Top) +')'+

'– '+

'('+ IntToStr(rect.Right) + ','+ IntToStr(rect.Bottom) +') '+

IntToStr(rect.Right

– rect.Left) + 'x'+ IntToStr(rect.Bottom –rect.Top);

//Определение стиля окна

LoadWindowStyle();

LoadWindowExStyle();

end;


Если вы внимательно просмотрели листинг 10.5, то наверняка заметили вызовы двух процедур в двух последних строках. Процедура LoadWindowStyle заполняет списки используемых и доступных оконных стилей (рис. 10.4), а процедура LoadWindowExStyle, соответственно, заполняет списки используемых и доступных дополнительных (или расширенных) стилей окна.

Реализация процедуры LoadWindowStyle приведена в листинге 10.6.

Листинг 10.6. Заполнение списков оконных стилей

procedure TfrmWindowProp.LoadWindowStyle();

var

i: Integer;

style: DWORD;

begin

style:= GetWindowLong(wnd, GWL_STYLE);

lstStyle.Clear();

lstAvailStyle.Clear();

//Выделение из 32-битного значения составляющих стиля окна

for i:= 0 to 177do

if styles[i].value and style <> 0 then

begin

//Стиль используется

lstStyle.Items.Add(styles[i].name);

styles[i].used:= True;

end

else

begin

//Стиль не используется

lstAvailStyle.Items.Add(styles[i].name);

styles[i].used:= False;

end;

end;


Вместо громоздкой проверки наличия в значении, возвращенном API-функцией GetWindowLong, битов каждого возможного стиля с помощью, например, функции case, здесь используется глобальный массив styles структур Stylelnfo. Объявление типа структуры (записи) StyleInfo осуществляется следующим образом:


type

StyleInfooo= record

value: DWORD; //Код стиля

name: String; //Текстовое обозначение стиля

used: Boolean; //Служебное поле

end;


Каждый элемент массива styles хранит информацию об определенном оконном стиле. Объявление этого массива, как и структуры StyleInfo и прочих рассмотренных в этом разделе типов данных, находится в модуле WindowData, расположенном на диске в папке с номером главы.

Ниже приведено объявление массива styles (флаги стиля, являющиеся комбинацией других флагов, в массив не попали) (листинг 10.7).

Листинг 10.7. Массив с информацией об оконных стилях

styles: array [0..17] of StyleInfo =

(

(value: WS_BORDER; name: 'WS_BORDER'),

(value: WS_CAPTION; name: 'WS_CAPTION'),

(value: WS_CHILD; name: 'WS_CHILD'),

(value: WS_CLIPCHILDREN; name: 'WS_CLIPCHILDREN'),

(value: WS_DISABLED; name: 'WS_DISABLED'),

(value: WS_DLGFRAME; name: 'WS_DLGFRAME'),

(value: WS_HSCROLL; name: 'WS_HSCROLL'),

(value: WS_MAXIMIZE; name: 'WS_MAXIMIZE'),

(value: WS_MAXIMIZEBOX; name: 'WS_MAXIMIZEBOX'),

(value: WS_MINIMIZE; name: 'WS_MINIMIZE'),

(value: WS_MINIMIZEBOX; name: 'WS_MINIMIZEBOX'),

(value: WS_OVERLAPPED; name: 'WS_OVERLAPPED'),

(value: WS_POPUP; name: 'WS_POPUP'),

(value: WS_SYSMENU; name: 'WS_SYSMENU'),

(value: WS_TABSTOP; name: 'WS_TABSTOP'),

(value: WS_THICKFRAME; name: 'WS_THICKFRAME'),

(value: WS_VISIBLE; name: 'WS_VISIBLE'),

(value: WS_VSCROLL; name: 'WS_VSCROLL')

);


Процедура LoadWindowExStyle реализована практически так же, как и LoadWindowStyle, только она заполняет списки lstExStyle и lstAvailExStyle и обращается к массиву exstyles, а не styles. Поэтому достаточно привести объявление только массива exstyles (листинг 10.8).

Листинг 10.8. Массив с информацией о дополнительных оконных стилях

exstyles: array [0..18] of StyleInfo =

(

(value: WS_EX_ACCEPTFILES; name: 'WS_EX_ACCEPTFILES'),

(value: WS_EX_APPWINDOW; name: 'WS_EX_APPWINDOW'),

(value: WS_EX_CLIENTEDGE; name: 'WS_EX_CLIENTEDGE'),

(value: WS_EX_CONTEXTHELP; name: 'WS_EX_CONTEXTHELP'),

(value: WS_EX_CONTROLPARENT; name: 'WS_EX_CONTROLPARENT'),

(value: WS_EX_DLGMODALFRAME; name: 'WS_EX_DLGMODALFRAME'),

(value: WS_EX_LAYERED; name: 'WS_EX_LAYERED'),

(value: WS_EX_LEFT; name: 'WS_EX_LEFT'),

(value: WS_EX_LEFTSCROLLBAR; name: 'WS_EX_LEFTSCROLLBAR'),

(value: WS_EX_MDICHILD; name: 'WS_EX_MDICHILD'),

(value: WS_EX_NOACTIVATE; name: 'WS_EX_NOACTIVATE'),

(value: WS_EX_NOINHERITLAYOUT; name: 'WS_EX_NOINHERITLAYOUT'),

(value: WS_EX_NOPARENTNOTIFY; name: 'WS_EX_NOPARENTNOTIFY'),

(value: WS_EX_RIGHTSCROLLBAR; name: 'WS_EX_RIGHTSCROLLBAR'),

(value: WS_EX_STATICEDGE; name: 'WS_EX_STATICEDGE'),

(value: WS_EX_TOOLWINDOW; name: 'WS_EX_TOOLWINDOW'),

(value: WS_EX_TOPMOST; name: 'WS_EX_TOPMOST'),

(value: WS_EX_TRANSPARENT; name: 'WS_EX_TRANSPARENT'),

(value: WS_EX_WINDOWEDGE; name: 'WS_EX_WINDOWEDGE')

);


Страницы книги >> Предыдущая | 1 2 3 4 5 6 7 8
  • 0 Оценок: 0

Правообладателям!

Данное произведение размещено по согласованию с ООО "ЛитРес" (20% исходного текста). Если размещение книги нарушает чьи-либо права, то сообщите об этом.

Читателям!

Оплатили, но не знаете что делать дальше?


Популярные книги за неделю


Рекомендации