Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Получить RTF-текст из RichEdit'а, в стороннем приложении 
:(
    Опции темы
Keeper89
Дата 28.12.2011, 03:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



Доброго времен суток.

Облазил весь интернете поисках примеров - все около. Подскажите, как сделать такую вещь.  smile 

Заранее спасибо.


--------------------
PM MAIL WWW   Вверх
RomanEEP
Дата 28.12.2011, 07:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: нет
Всего: 8



SaveToStream уже не катит?
PM MAIL   Вверх
RomanEEP
Дата 28.12.2011, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: нет
Всего: 8



Курить вот это:
Код

procedure TRichEditStrings.SaveToStream(Stream: TStream; Encoding: TEncoding);
var
  EditStream: TEditStream;
  TextType: Longint;
  StreamInfo: TRichEditStreamInfo;
  Converter: TConversion;
  Preamble: TBytes;
{$IF DEFINED(CLR)}
  Handle: GCHandle;
{$IFEND}
begin
  if FConverter <> nil then
    Converter := FConverter
  else
    Converter := RichEdit.DefaultConverter.Create;
  StreamInfo.Stream := Stream;
  StreamInfo.Converter := Converter;
  StreamInfo.PlainText := PlainText;
  StreamInfo.Encoding := Encoding;
  try
{$IF DEFINED(CLR)}
    Handle := GCHandle.Alloc(TObject(StreamInfo));
{$IFEND}
    try
      with EditStream do
      begin
{$IF DEFINED(CLR)}
        dwCookie := DWORD_PTR(IntPtr(Handle));
{$ELSE}
        dwCookie := DWORD_PTR(@StreamInfo);
{$IFEND}
        pfnCallBack := StreamSave;
        dwError := 0;
      end;
      if PlainText then
      begin
        TextType := SF_TEXT or SF_UNICODE;
        if Encoding <> nil then
        begin
          Preamble := Encoding.GetPreamble;
          if Length(Preamble) > 0 then
{$IF DEFINED(CLR)}
            Stream.WriteBuffer(Preamble, Length(Preamble));
{$ELSE}
            Stream.WriteBuffer(Preamble[0], Length(Preamble));
{$IFEND}
        end;
      end
      else
        TextType := SF_RTF;
      SendGetStructMessage(RichEdit.Handle, EM_STREAMOUT, TextType, EditStream, True);
      if EditStream.dwError <> 0 then
        raise EOutOfResources.Create(sRichEditSaveFail);
    finally
{$IF DEFINED(CLR)}
      Handle.Free;
{$IFEND}
    end;
  finally
    if FConverter = nil then Converter.Free;
  end;
end;

PM MAIL   Вверх
Keeper89
Дата 28.12.2011, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



RomanEEP, где сказано про собственное приложение?
Вот хороший пример:
Код

unit MainUnit;

interface

uses
 Windows, Messages, Graphics, Controls, Forms, ComCtrls,
 StdCtrls, Classes, SysUtils, Dialogs;

type
 TForm1 = class(TForm)
   Edit1: TEdit;
   Button1: TButton;
   Memo1: TMemo;
   Edit2: TEdit;
   procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure Button1Click(Sender: TObject);
 end;

var
 Form1: TForm1;

implementation

uses RichEdit;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
{$DEFINE DEBUG_FIND}
var
 MainWindowHandle, RichEditWHandle: THandle;
 ProcessID : Cardinal;
 ProcessHandle : THandle;
 StructTextEx: TGetTextEx;
 StructTextLength: TGetTextLengthEx;
 PStructTextLength, PStructTextEx, PTextBuffer: Pointer;
 BytesWriten, RichEditTextLength: DWORD;
 TextBuffer: array of Char;
begin

 {$IFDEF DEBUG_FIND}
   // Заполняем данные для отладки
   // В качестве примера работаем с WordPad-ом
   Edit1.Text := "Document - WordPad";
   Edit2.Text := "RICHEDIT50W";
 {$ENDIF}

 // Ищем окно
 MainWindowHandle := FindWindow(nil , PChar(Edit1.Text));
 if MainWindowHandle = 0 then RaiseLastOSError;
 RichEditWHandle := FindWindowEx(MainWindowHandle, 0, PChar(Edit2.Text), nil);
 if RichEditWHandle = 0 then RaiseLastOSError;

 // Узнаем ID процесса
 GetWindowThreadProcessId(MainWindowHandle, @ProcessID);
 if ProcessID = 0 then RaiseLastOSError;

 // Открываем процесс
 ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, True, ProcessID);
 if ProcessHandle = 0 then RaiseLastOSError;
 try

   // Выделяем в нем память под структуру TGetTextLengthEx
   PStructTextLength := VirtualAllocEx(ProcessHandle, nil,
     SizeOf(TGetTextLengthEx), MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
   if PStructTextLength = nil then RaiseLastOSError;
   try

     // Подготавливаем структуру...
     StructTextLength.flags := GTL_NUMBYTES or GTL_USECRLF;
     StructTextLength.codepage := CP_ACP;

     // ...и пишем ее в память процесса
     if not WriteProcessMemory(ProcessHandle, PStructTextLength,
       @StructTextLength, SizeOf(TGetTextLengthEx),
       BytesWriten) then RaiseLastOSError;
     if BytesWriten <> SizeOf(TGetTextLengthEx) then RaiseLastOSError;

     // Отправляем сообщение удаленному RichEdit,
     // чтобы узнать необходимый размер буффера
     RichEditTextLength := SendMessage(RichEditWHandle,
       EM_GETTEXTLENGTHEX , Integer(PStructTextLength), 0);

   finally
     // Освобождаем выделенную под TGetTextLengthEx память
     VirtualFreeEx(ProcessHandle, PStructTextLength, 0, MEM_RELEASE);
   end;

   // Выделяем память под структуру TGetTextEx
   PStructTextEx := VirtualAllocEx(ProcessHandle, nil,
     SizeOf(TGetTextEx), MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
   if PStructTextEx = nil then RaiseLastOSError;
   try

     // Подготавливаем структуру...
     ZeroMemory(@StructTextEx, SizeOf(TGetTextEx));
     StructTextEx.flags := GT_USECRLF;
     StructTextEx.cb := RichEditTextLength;

     // ...и пишем ее в память процесса
     if not WriteProcessMemory(ProcessHandle, PStructTextEx,
       @StructTextEx, SizeOf(TGetTextEx),
       BytesWriten) then RaiseLastOSError;
     if BytesWriten <> SizeOf(TGetTextEx) then RaiseLastOSError;

     // Выделяем память под текстовый буффер
     PTextBuffer := VirtualAllocEx(ProcessHandle, nil,
     RichEditTextLength, MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
     if PTextBuffer = nil then RaiseLastOSError;
     try

       // отправляем сообщение
       SendMessage(RichEditWHandle, EM_GETTEXTEX, Integer(PStructTextEx),
         Integer(PTextBuffer));

       // Читаем, то, что у нас скопировалось
       SetLength(TextBuffer, RichEditTextLength);
       if not ReadProcessMemory(ProcessHandle, PTextBuffer, @TextBuffer[0],
         RichEditTextLength, BytesWriten) then RaiseLastOSError;

       Memo1.Text := String(TextBuffer);

     finally
       // Освобождаем выделенную под тестовый буффер память
       VirtualFreeEx(ProcessHandle, PTextBuffer, 0, MEM_RELEASE);
     end;

   finally
     // Освобождаем выделенную под TGetTextEx память
     VirtualFreeEx(ProcessHandle, PStructTextEx, 0, MEM_RELEASE);
   end;

 finally
   // Закрываем процесс
   CloseHandle(ProcessHandle);
 end;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 ReleaseCapture;
 SendMessage(Handle, WM_SYSCOMMAND, SC_MOVE or HTCAPTION, 0);
end;

end.

http://forum.sources.ru/index.php?showtopi...t&p=1245162

Но здесь, просто текст, не EM_STREAMOUT. Пробовал его переделать - безрезультатно.

Это сообщение отредактировал(а) Keeper89 - 28.12.2011, 12:09


--------------------
PM MAIL WWW   Вверх
RomanEEP
Дата 29.12.2011, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: нет
Всего: 8



так тем пособом что я писал выдирается из любого РичЭдита)) просто хандле нужный тебе подставляешь и всё. Всю логику работы смотри в ComCtrls.pas, в VCL всё написано до нас и искать ничего не надо
PM MAIL   Вверх
Keeper89
Дата 29.12.2011, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



Это же другой процесс. И в этом процессе другая адресация и никто не будет знать о колбэке в нашем адресом пространстве.
Или я не прав?  


--------------------
PM MAIL WWW   Вверх
RomanEEP
Дата 29.12.2011, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: нет
Всего: 8



мы не работаем с адресами в другом процессе. мы отправляем сообщение, каллбэк которого всегда будет в адресном пространстве того процесса из которого оно было отправлено
PM MAIL   Вверх
RomanEEP
Дата 29.12.2011, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: нет
Всего: 8



прошу прощения, был не прав... каллбэк в другом процессе не прокатит
вот тут предлагается выполнить этот код через подгружаемую к процессу дллку 
http://www.progtown.com/topic176317-how-to...he-program.html
и еще есть вариант просто использовать буфер обмена
PM MAIL   Вверх
Keeper89
Дата 29.12.2011, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



Библиотека - не желаемый вариант. А с буфером как?

Добавлено через 1 минуту и 36 секунд
Возможен ли первоначальный вариант без библиотеки вообще или нет? Чтобы сразу определиться куда идти smile


--------------------
PM MAIL WWW   Вверх
RomanEEP
Дата 29.12.2011, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: нет
Всего: 8



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

Через буфер - просто
Код

  SendMessage(ExternalHandle, EM_SETSEL, 0, -1);
  SendMessage(ExternalHandle, WM_COPY, 0, 0);
  RichEdit.PasteFromClipboard;

PM MAIL   Вверх
Keeper89
Дата 29.12.2011, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



Насколько я помню WM_COPY копирует только текст. Или нет?

Вот с первым вариантом пример и хотелось бы. 


--------------------
PM MAIL WWW   Вверх
Keeper89
Дата 29.12.2011, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



В общем, пока решил следующим образом:
Код

class function TRichEditGrabber.TryGetRTFText(RichEditHandle:
    THandle; out QuestionRTF: string): Boolean;
var
  RichEdit: TRichEdit;
  ss: TStringStream;
begin
  Result := False;

  SendMessage(RichEditHandle, EM_SETSEL, 0, -1);
  SendMessage(RichEditHandle, WM_COPY, 0, 0);
  SendMessage(RichEditHandle, EM_SETSEL, 0, 0);

  RichEdit := TRichEdit.CreateParented(HWND_MESSAGE);
  ss := TStringStream.Create;
  try
    RichEdit.PasteFromClipboard;
    RichEdit.Lines.SaveToStream(ss);
    QuestionRTF := ss.DataString;
    Result := True;
  finally
    FreeAndNil(ss);
    FreeAndNil(RichEdit);
  end;
end;

Но буду ждать примеров первого вариант.


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0552 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.