Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (все версии) - часть 4

Автор: Mandor Sawall
Дата сообщения: 08.08.2008 10:37
Maks150988

Код: function GetModuleInfo(szModuleName: PChar; dwMaxNameLen: DWORD; szGUID: PChar; dwMaxGUIDLen: DWORD; szModuleDescr: PChar; dwMaxDescrName: DWORD): BOOL; stdcall;
begin
dwMaxNameLen := strlen(PChar(TszModuleName)) + 1;
//^^^ Ето ненужно, у вас параметр по стойност, не по адрес.
StrLCopy(szModuleName, PChar(TszModuleName), dwMaxNameLen);
dwMaxDescrName := strlen(PChar(TszModuleDescr)) + 1;
//^^^ Ето тоже.
StrLCopy(szModuleDescr, PChar(TszModuleDescr), dwMaxDescrName);
dwMaxGUIDLen := strlen(PChar(TszGUID)) + 1;
//^^^ Ето тоже.
StrLCopy(szGUID, PChar(TszGUID), dwMaxGUIDLen);
Result := TRUE;
end;
Автор: Maks150988
Дата сообщения: 08.08.2008 16:11
Вобщем код модуля такой сделал, но пока толком не исправлял:
[more]
library module_glxtlt;

{$R module_glxtlt.res}

uses
Windows, Messages, SysUtils;

type
FN_HTTPDOWNLOAD = function(szURL: PChar;
szMethod: PChar;
szArgs: PChar;
szReferrer: PChar;
szContentType: PChar;
pBuffer: pBYTE;
dwMaxBufferLen: DWORD): DWORD; stdcall;

const
RES_MENU = 101;
TszModuleName = 'Модуль';
TszServerName = 'vpn.ru';
TszGUID = '{EC7B9ECC-8FC9-4c82-97BC-3CDB3E2C2B31}';
TszForgetPasswordLink = 'http://ссылка';
TszURL = 'http://ссылка';
TszModuleDescr = 1600;
TszLoginHint = 1601;
TszPasswordHint = 1602;

function GetModuleIcon: HICON; stdcall;
begin
Result := LoadImage(hInstance, MAKEINTRESOURCE(RES_MENU), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE or LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS);
end;

function GetModuleInfo(szModuleName: PChar; dwMaxNameLen: DWORD; szGUID: PChar; dwMaxGUIDLen: DWORD; szModuleDescr: PChar; dwMaxDescrName: DWORD): BOOL; stdcall;
begin
dwMaxNameLen := StrLen(PChar(TszModuleName)) + 1;
StrLCopy(szModuleName, PChar(TszModuleName), dwMaxNameLen);
dwMaxDescrName := StrLen(PChar(Format(LoadStr(TszModuleDescr), [TszModuleName]))) + 1;
StrLCopy(szModuleDescr, PChar(Format(LoadStr(TszModuleDescr), [TszModuleName])), dwMaxDescrName);
dwMaxGUIDLen := StrLen(PChar(TszGUID)) + 1;
StrLCopy(szGUID, PChar(TszGUID), dwMaxGUIDLen);
Result := TRUE;
end;

function GetModuleHints(szLoginHint: PChar; dwLoginHintLen: DWORD; szPasswordHint: PChar; dwPasswordHintLen: DWORD; szForgetPasswordLink: PChar; dwLinkLen: DWORD): BOOL; stdcall;
begin
dwLoginHintLen := StrLen(PChar(Format(LoadStr(TszLoginHint), [TszModuleName, TszServerName]))) + 1;
StrLCopy(szLoginHint, PChar(Format(LoadStr(TszLoginHint), [TszModuleName, TszServerName])), dwLoginHintLen);
dwPasswordHintLen := StrLen(PChar(Format(LoadStr(TszPasswordHint), [TszModuleName, TszServerName]))) + 1;
StrLCopy(szPasswordHint, PChar(Format(LoadStr(TszPasswordHint), [TszModuleName, TszServerName])), dwPasswordHintLen);
dwLinkLen := StrLen(PChar(TszForgetPasswordLink)) + 1;
StrLCopy(szForgetPasswordLink, PChar(TszForgetPasswordLink), dwLinkLen);
Result := TRUE;
end;

{ Состояние записи, получение данных }
{ const char* szAccount - логин }
{ const char* szPassword - пароль }
{ double* dBalance - баланс }
{ double* dOverdraft - овердрафт }
{ double* dActive - активные сессии (если есть) }
{ double* dMinutes - минуты (если есть) }
{ char* szTarif - тарифный план }
{ DWORD dwMaxTarifLen - максимальная длина буффера }
{ char* szMessage - сообщение об ошибке }
{ DWORD dwMaxMessageLen - максимальная длина буффера }
{ FN_HTTPDOWNLOAD httpDownload - указатель на функцию (см. объявление FN_HTTPDOWNLOAD) }

function GetAccountState(szAccount: PChar; szPassword: PChar; dBalance: pDouble; dOverdraft: pDouble; dActive: pDouble; dMinutes: pDouble; szTarif: PChar; dwMaxTarifLen: DWORD; dwTarifDays: pDWORD; dwTarifDaysLeft: pDWORD; szMessage: PChar; dwMaxMessageLen: DWORD; httpDownload: FN_HTTPDOWNLOAD): BOOL; stdcall;
begin
Result := TRUE;
end;

function GetAccountURLAndPostData(szAccount: PChar; szPassword: PChar; szURL: PChar; dwURLLen: DWORD; szPOSTData: PChar; dwPOSTDataLen: DWORD): BOOL; stdcall;
begin
dwURLLen := StrLen(PChar(TszURL)) + 1;
StrLCopy(szURL, PChar(TszURL), dwURLLen);
wsprintf(szPOSTData, PChar(Format('?language=russian&user=%s&passwd=%s&logined=1', [szAccount, szPassword])));
Result := TRUE;
end;

exports
GetModuleIcon,
GetModuleInfo,
GetModuleHints,
GetAccountState,
GetAccountURLAndPostData;

begin
end.
[/more]
Но мне чего-то непонятно как отправить POST запрос username=blabla&password=blabla например на адрес http://ссылка, используя колбек функцию FN_HTTPDOWNLOAD. И все это выполнить через функцию GetAccountState. Вобщем как нужно прописать этот запрос,для меня неясно. Значения szAccount и szPassword передаются из программы и всталвяются в сам запрос.
Автор: Pawo
Дата сообщения: 08.08.2008 16:38
Нашел исходник высокоточного таймера, но при компиляции находит ошибку "Record, object or class required" в QW.QuadPart и ET.QuadPart. Как исправить ошибку?
Автор: V1s1ter
Дата сообщения: 08.08.2008 17:03
Pawo

Цитата:
Нашел исходник высокоточного таймера, но при компиляции находит ошибку "Record, object or class required" в QW.QuadPart и ET.QuadPart. Как исправить ошибку?


Пиши ULARGE_INTEGER(QW).QuadPart; вместо QW.QuadPart; и будет тебе счастье.
Автор: akaGM
Дата сообщения: 08.08.2008 17:10
Pawo
ну убери поля .QuadPart

т.е., например вместо
ClockRate := QW.QuadPart;
пиши
ClockRate := QW;

должно помочь...
если не поможет, тогда тоже убери эти поля, а вместо TLargeInteger используй Int64,
хотя это одно и тоже...
Автор: Maks150988
Дата сообщения: 12.08.2008 16:59
Ммм, неужели тут никто не может помочь... =) Я правда, если честно, не знаю, но уже прям принцип доделать плагин. Автор перевоначального исходника не желает давать свою реализацию, подозреваю что там уж слишком "подсудный" для него код то что возвратит сервер на его запрос о биллинге.

Вобщем ситуция такова. Есть:


Код:
type
FN_HTTPDOWNLOAD = function(szURL : PChar; szMethod: PChar; szArgs: PChar; szReferrer : PChar; szContentType : PChar; pBuffer : pBYTE; dwMaxBufferLen : DWORD) : DWORD; stdcall;
Автор: DmitryKz
Дата сообщения: 18.08.2008 23:45
Ребята, помогите разобраться. Нужно подсчитать употребление каждого слова в Вордовском документе и заполнить таблицу Парадокс, в которой три поля: WordID, Word, Count. Вторичный индекс построен по полю Word. Доступ к таблице через БДЕ.
Пример тестовый, будет нужен в дальнейшем. На форме кнопка, по нажатию которой загружается документ. Два поля редактирования: в одном - общее кол-во слов. Во втором должнен бы отображаться номер текущего слова. Ну и сетка DBGrid. Вот код:

Цитата:
procedure TForm1.btnOpenClick(Sender: TObject);
var
Word_: variant;
i: integer;
tWord: string;
begin
if not OpenDialog1.Execute then exit;
W := CreateOleObject('Word.Application');
W.Documents.Open(OpenDialog1.FileName);
W.Documents.Item(OpenDialog1.FileName).Activate;
Word_ := W.ActiveDocument.Words;
DataModule2.words.Exclusive := true;
DataModule2.words.Active := true;
if not DataModule2.words.IsEmpty then DataModule2.words.EmptyTable;
DataModule2.words.IndexName := 'Words';
Edit1.Text := IntToStr(Word_.Count);
DataModule2.words.DisableControls;
for i := 1 to Word_.Count do
begin
tWord := Word_.Item(i);
if tWord[1] <= ' ' then continue;
Edit2.Text := IntToStr(i);
if DataModule2.words.FindKey([tWord]) then begin
DataModule2.words.Edit;
DataModule2.words['Count'] := DataModule2.words['Count'] + 1;
DataModule2.words.Post; end
else begin
DataModule2.words.Insert;
DataModule2.words['Word'] := tWord;
DataModule2.words['Count'] := 1; end;
end;
DataModule2.words.EnableControls;

end;

Все работает, но есть несколько проблем, которые не знаю как решить.
Во-первых, очень медленно заполняется таблица. Есть небольшой тестовый документ в сто тысяч слов. 10 тысяч обрабатывается за 10 минут - получается весь документ с учетом перестройки таблицы по индексу должен обрабатываться что-то около 2 часов. Может, есть какие-то другие технологии, более быстрые?
Во-вторых, во время заполнения таблицы форма становится "застывшей" - ее не подвигать, и, соответственно, поля редактирования не обновляются (код Edit1.Text := IntToStr(Word_.Count); Edit2.Text := IntToStr(i);. Что-то с этим можно сделать?
Извиняюсь за возможно корявый код, как уже сказал - пример тестовый
Автор: ShIvADeSt
Дата сообщения: 19.08.2008 03:41

Цитата:
for i := 1 to Word_.Count do
begin
tWord := Word_.Item(i);
if tWord[1] <= ' ' then continue;
Edit2.Text := IntToStr(i);
Application.ProcessMessages //добавить, чтобы форма реагировала (вроде так пишется)
if DataModule2.words.FindKey([tWord]) then begin
DataModule2.words.Edit;
DataModule2.words['Count'] := DataModule2.words['Count'] + 1;
DataModule2.words.Post; end
else begin
DataModule2.words.Insert;
DataModule2.words['Word'] := tWord;
DataModule2.words['Count'] := 1; end;
end;
DataModule2.words.EnableControls;


далее, попробуй считать документ ворда (или слова) в память - ускорение в разы будет.
Автор: shulum
Дата сообщения: 19.08.2008 09:34

Цитата:
Во-вторых, во время заполнения таблицы форма становится "застывшей" - ее не подвигать, и, соответственно, поля редактирования не обновляются (код Edit1.Text := IntToStr(Word_.Count); Edit2.Text := IntToStr(i);. Что-то с этим можно сделать?

Загнать в отдельный поток ... если лень возиться с созданием оного самостоятельно, то можно просто воспользоваться компонентом из комплекта JVCL (TJvThread), либо внутри цикла обновлять эти компоненты ... Edit1.refresh
Автор: DmitryKz
Дата сообщения: 19.08.2008 09:42
ShIvADeSt
Спасибо, а можно уточнить, что значит считать документ ворд в память? Доступ к нему через COM.
Автор: lerthe61
Дата сообщения: 19.08.2008 10:28

Цитата:
Во-первых, очень медленно заполняется таблица. Есть небольшой тестовый документ в сто тысяч слов. 10 тысяч обрабатывается за 10 минут - получается весь документ с учетом перестройки таблицы по индексу должен обрабатываться что-то около 2 часов. Может, есть какие-то другие технологии, более быстрые?

Почему бы вам не воспользоваться профайлером?
Автор: ShIvADeSt
Дата сообщения: 19.08.2008 11:18
DmitryKz

Цитата:
Ребята, помогите разобраться. Нужно подсчитать употребление каждого слова в Вордовском документе и заполнить таблицу Парадокс, в которой три поля: WordID, Word, Count.

Это принципиально, чтобы парадокс таблица была? Просто ИМХО проще было бы сделать акцезовскую таблицу, туда скинуть ВСЕ слова (да да, именно все), а потом уже в грид грузануть что нить типа такого
select Word,Count(Word) from MyTable group by Word
то есть по идее должно будет вывестись уникальное слово и рядом с ним счетчик в таблице.

О другая идея. Создаешь динамический массив, наподобие твоей базы (работа с памятью шустрей чем с базой ИМХО). Туда скидываешь свои слова и сколько уже найдено, по массиву бегаешь в поисках слов (заодно увеличивая значения). а потом уже скидываешь массив в базу

Цитата:
DataModule2.words.Edit;
DataModule2.words['Count'] := DataModule2.words['Count'] + 1;
DataModule2.words.Post; end

так лучше не надо (фигова туча обращений на открытие закрытие.
Лучше один раз вверху едит, а потом после окончания обработки текста пост. Хотя я Парадоксом не работал давно, но думаю ускорение должно быть.
И еще попробуй отследить слабое место, вначале прогони документик без записи в базу.ю чтобы опредилть, что именно тормозит - поиск по документу или запись в базу.
Автор: DmitryKz
Дата сообщения: 19.08.2008 12:05

Цитата:
О другая идея. Создаешь динамический массив

Угу, я уже испытал эту идею. Сразу обнаружилось слабое место - обращение к документу через COM - заполнение массива идет так же медленно, как заполнение базы напрямую. Просто если цикл прогнать с отображением итерации цикла в Эдите - десяток (даже меньше) секунд. Получается, надо получать готовый текст сразу и затем парсить на отдельные слова? Тут, кстати, другая еще проблема обозначилась - мне нужен Юникодный текст (в документе греческие и иврит слова). Как его выцепить?
Автор: anfilat
Дата сообщения: 19.08.2008 12:36
DmitryKz

Цитата:
Тут, кстати, другая еще проблема обозначилась - мне нужен Юникодный текст (в документе греческие и иврит слова). Как его выцепить?

Вообщето COM только с юникодом работает. Поэтому замени tWord: string; на tWord: WideString; и будет тебе счастье

Цитата:
Сразу обнаружилось слабое место - обращение к документу через COM

А ты не через IDispatch работай, а через IUnknown - будет быстрее. В Delphi для этого готовый компонент должен быть, на вкладке ActiveX кажется
Автор: ShIvADeSt
Дата сообщения: 19.08.2008 14:33
DmitryKz
Формат doc принципиален? Есть ли вариант сохранить в rtf, а его уже потом грузить в скрытый контрол и с ним уже работать?
Автор: greeng
Дата сообщения: 19.08.2008 15:48
вообщим написал приложение для работы с таблицами DBF формата
есть файл настроек dat.ini откуда берется номер компа(участка) и путь к базам и файлу PDOXUSRS.NET
далее при открытии таблицы она вилтруется по номер компа(участка) , тоесть при одновременном открытии несколькими пользователями с разными настройками участков в файле dat.ini каждый будет видить только свои записи.

вопрос!

все будет нормально работать не будут ли косяков при редактировании и сохранении таблиц?

если нет то предложите плиз свои варианты.
С Уважением ко всем Григорий.
Автор: V1s1ter
Дата сообщения: 19.08.2008 16:56
greeng
При работе по сети через BDE могут проити глюки. Я боролся с ними почти два года, в конце концов переделал все базы под AbsoluteDataBase (В нем есть конверитилка и переделка программы заняла около одного дня, а программа здоровая и таблиц 486 штук). Я это написал ести ты планируеш разработку новой программы/базы. Если же в наследство осталиь DBF файлы+другие работающие с ними программы, порекомендую следующее.
Вариант 1. Работай с компонентами TQuery и TSQL, не используй TTable, работа через этот компонент в условиях сети приводила к потере данных.
Вариант 2. Работай с компонентами типа TMemoryTable. Получаеш свои записи на локальную машины, работаеш с ними и в пакетном режиме записываеш назад в базу.
Вариант 3. Оставь как написал, при небольшом трафике и отсутствии BLOB-полей все должно работать.

С BDE я мучался долго и сам прописывал и настройки и специалисты мне помогали и "специалисты" мне тоже советовали - результат в первых строках...
Автор: Maks150988
Дата сообщения: 20.08.2008 01:46
Вобщем, разобрался с этим модулем. И еще хотел узнать, может кто-то делал функцию для извлечения подстроки?
Мой вариант таков:

Код:
function ExtractSubString(Source, First, Second : String) : String;
var
S : String;
T : String;
P : Integer;
begin
S := Source;
// находим символ, с которого начинается первая искомая строка
P := Pos(First, Source);
// начинаем удалять с первой позиции число символов + число символов,
// котороое мы подсчитали длиной первой искомой строки
Delete(S, 1, P - 1 + Length(First));
// получаем требуемую извлеченную строку для дальнейшей обработки
// находим символ, с которого начинается вторая искомая строка
P := Pos(Second, S);
// скопируем временно строку с полученной позиции для подсчета ее длины
T := Copy(S, P, Length(S));
// начинаем удалять с первой позиции число символов + число символов,
// котороое мы подсчитали длиной второй искомой строки
Delete(S, Length(S) - Length(T) + 1, Length(T));
// возвращаем нужный нам результат в виде подстроки
Result := S;
end;
Автор: Jokerjar79
Дата сообщения: 20.08.2008 04:38
Maks150988, на счет первого вопроса: не нужна переменная S, можно работать прям с Source - функция не изменит поданную переменную, т.к. она копируется в стек. Ну и в конце малость лишнего. В общем, можно сделать так:


Код: function ExtractSubString(Source, First, Second: string): string;
var
i1, i2: integer;
begin
i1 := pos(First, Source) + length(First);
delete(Source, 1, i1 - 1);
i2 := pos(Second, Source) - 1;
result := copy(Source, 1, i2);
end;
Автор: Maks150988
Дата сообщения: 20.08.2008 07:58
Jokerjar79
Спасибо за функцию.
Вас не затруднит выцепить из модуля SysUtils FormatFloat функцию? Якак всегда поторопился и поставил урезанно Delphi и pas файлов нет. А диск опять куда-то подевал. У меня есть модуль Lenin_SysUtils, но чего-то не пойму. Компилятор выдает ошибки. Там указано как:


Код:
{$L Lenin_Ffmt.obj}

function FloatToTextFmt(Buffer: PChar; const Value;ValueType: TFloatValue;
Format: PChar): Integer;
begin end;

function FormatFloat(const Format: string; Value: Extended): string;
var
Buffer: array[0..255] of Char;
begin
SetString(Result, Buffer, FloatToTextFmt(Buffer, Value, fvExtended, PChar(Format)));
end;
Автор: Jokerjar79
Дата сообщения: 20.08.2008 08:27
Вытащить оттуда эту функцию затруднительно, т.к. она вызывает другие функции, написанные с помощью ассемблерных вставок, а также использует инициализируемые константы (к примеру, символ разделителя целой и дробной частей, символ отделения тысяч). Проще найти модуль целиком
Автор: Dimoniusis
Дата сообщения: 20.08.2008 08:29
Maks150988 у тебя 2 делита - имхо они работают весьма медленно. Если вызовы будут редки - можно оставит. Я бы сделал байт копированием - работает очень быстро. Пробегаемся по строке проверяя на начало. Если нашли - ставим булевскую переменную и SetLength результу. И так до второго куска.
Автор: Maks150988
Дата сообщения: 20.08.2008 09:30
Jokerjar79
А вы случаем не занете где такой модуль то найти? Решил поискать на сайте KOL и порылся в исходниках, думал там есть, все-таки большая часть VCL кода в ихних функциях сделана ассемблерными вставками, но не нашел.
Dimoniusis
Придется наверное парсер сделать как вы и предложили надо понимать.
Автор: Jokerjar79
Дата сообщения: 20.08.2008 10:03
Maks150988, какой версией Delphi пользуетесь? Думаю, кто-то поделится, хотя лучше, конечно же, найти дистрибутив и выполнить полную установку, а то неизвестно какие еще сюпризы может приподнести урезанная версия
Автор: Maks150988
Дата сообщения: 20.08.2008 10:09
Jokerjar79
Делфи 7
Автор: DmitryKz
Дата сообщения: 20.08.2008 18:59
anfilat
Попытался я сделать раннее связывание. Сделал импорт. Получившийся код:

Цитата:
implementation

uses dm, Word_TLB;

var
IfWordApp: IInterface;
IfDocs: Documents;
IfApp: WordApplication;
IfOpenDoc: WordDocument;
IfAllWords: Words;

{$R *.dfm}

procedure TForm1.btnOpenClick(Sender: TObject);
var
FlName: OleVariant;
i: integer;
tWord: WideString;

begin
if not OpenDialog1.Execute then exit;
FlName := OpenDialog1.FileName;

IfWordApp := CoWordApplication.Create;
IfWordApp.QueryInterface(Documents, IfDocs);

IfOpenDoc := IfDocs.Open(FlName, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam);

IfDocs.Item(FlName).Activate;

IfWordApp.QueryInterface(WordApplication, IfApp);
IfAllWords := IfApp.ActiveDocument.Words;

DataModule2.words.Exclusive := true;
DataModule2.words.Active := true;
if not DataModule2.words.IsEmpty then DataModule2.words.EmptyTable;
DataModule2.words.IndexName := 'Words';
DataModule2.words.DisableControls;

Edit1.Text := IntToStr(IfAllWords.Count);

for i := 1 to IfAllWords.Count do
begin
tWord := IfAllWords.Item(i).Text;
Edit2.Text := IntToStr(i);
if tWord[1] <= ' ' then continue;
Application.ProcessMessages;
if DataModule2.words.FindKey([tWord]) then begin
DataModule2.words.Edit;
DataModule2.words['Count'] := DataModule2.words['Count'] + 1;
DataModule2.words.Post; end
else begin
DataModule2.words.Insert;
DataModule2.words['Word'] := tWord;
DataModule2.words['Count'] := 1; end;
end;
DataModule2.words.EnableControls;

end;

Word (2007) запускается, но на методе IfOpenDoc := IfDocs.Open(FlName, EmptyParam ... программа вылетает с ошибкой:

Цитата:
Project DBWords.exe raised exception class EAccessViolation with message 'Access violation at address 004D3E9A in module 'DBWords.exe'. Read of address 00000000'. Process stopped. Use Step or Run to continue.

Что не так сделано?
Автор: RomanTim
Дата сообщения: 20.08.2008 23:21
DmitryKz
А почему ты решил, что объект, реализующий WordApplication, реализует и Documents? Вообще-то Documents это его свойство, а QueryInterfaice скорее всего возвращает ошибку, что интерфейс не поддерживается.
Попробуй так:
Код: uses WordXP;
...
var
app: WordApplication;
docs: Documents;
begin
app := CoWordApplication.Create;
if app <> nil then begin
docs := app.Documents;
if docs <> nil then begin
...
end;
end;
end;
Автор: DmitryKz
Дата сообщения: 21.08.2008 01:28
RomanTim
Так сработало, хотя все равно не понимаю, почему со сделанным через импорт модулем Word_TLB не хочет.
По этому способу я не отметил никакого ускорения работы в сравнении с использованием IDispatch. Придется парсить слова.
Автор: ShIvADeSt
Дата сообщения: 21.08.2008 02:08
DmitryKz
Вот что нагуглил

Код:
Получение информации из Word

Если кто-то не помнит — Word когда-то был текстовым процессором, поэтому из уважения к его истории в нем эти функции все еще присутствуют. Информацию из Word можно получить через интерфейс «IdataObject». Для получения указателя на этот интерфейс необходимо использовать функцию «QueryInterface».

Документы Word поддерживают стандартные форматы CF_TEXT и CF_METAFILEPICT так же как ряд других специфических форматов, включая RTF и structured storage. Для стандартных форматов используются константы значений переменной «cfFormat», но для других форматов нужно делать запрос, используя функцию «EnumFormatEtc». Эта функция возвратит список обеспечиваемых форматов. Требуемый формат из этого списка затем передается функции «GetData» интерфейса «IDataObject». Значение cfFormat для одинаковых форматов может различаться на разных компьютерах, поэтому всегда должно находиться с помощью функции «EnumFormatEtc». Для подробной информации относительно методов интерфейса «IdataObject» можно обратиться к файлам помощи по программированию в Win32.

Код:
uses Word_TLB;

function GetRTFFormat(DataObject: IDataObject; var RTFFormat: TFormatEtc):
Boolean;
var
Formats: IEnumFORMATETC;
TempFormat: TFormatEtc;
cfRTF: LongWord;
Found: Boolean;
begin
try
OleCheck(DataObject.EnumFormatEtc(DATADIR_GET, Formats));
cfRTF := RegisterClipboardFormat('Rich Text Format');
Found := False;
while (not Found) and (Formats.Next(1, TempFormat, nil) = S_OK) do
if (TempFormat.cfFormat = cfRTF) then begin
RTFFormat := TempFormat;
Found := True;
end;
Result := Found;
except
Result := False;
end;
end;

procedure GetRTF(WordDoc: _Document);
var
DataObject: IDataObject;
RTFFormat: TFormatEtc;
ReturnData: TStgMedium;
Buffer: PChar;
begin
if (Assigned(WordDoc)) then try
WordDoc.QueryInterface(IDataObject, DataObject);
if GetRTFFormat(DataObject, RTFFormat) then begin
OleCheck(DataObject.GetData(RTFFormat, ReturnData));
//RTF is passed through global memory
Buffer := GlobalLock(ReturnData.hglobal);
//Buffer is a pointer to the RTF text
//Insert code here to handle the RTF text (ie. save it, display it etc.)
GlobalUnlock(ReturnData.hglobal);
end;
except
ShowMessage('Error while getting RTF');
end;
end;
Автор: DmitryKz
Дата сообщения: 21.08.2008 17:26
ShIvADeSt
Спасибо за интересную статью! Тему открою, только освобожусь немного от работы.

Страницы: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667

Предыдущая тема: Глобальные переменные в разных формах с++ builder 'a.


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.