Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 18.07.2021, 16:07
Lighting Lighting вне форума
Прохожий
 
Регистрация: 18.07.2021
Сообщения: 5
Версия Delphi: Delphi 10.4
Репутация: 10
По умолчанию Как в окне JvRichEdit определить надстрочные и подстрочные символы?

Не могу сам решить эту задачу.
Есть текст, в котором надо выловить надстрочные и подстрочные символы. Как я понял, надо использовать EM_GETCHARFORMAT, но как, я не пойму.
Я использую библиотеку JEDI. Добавил в uses помимо JvRichEdit еще и RichEdit, потому как без него возникает ошибка в объявлении переменной CF:TCharFormat2;.
Пробую отслеживать dwMask и yOffset (да и другие варианты, которые нашел в примерах в интернете), но это не срабатывает...
Помогите решить задачу или посоветуйте учебник, в котором это было бы расписано, если такой существует, я вот найти не могу.
Код:
procedure TForm1.Button1Click(Sender: TObject);
var i:integer; CF:TCharFormat2;
 
begin
for i:=1 to Length(RichEdit1.Text) do begin  //Искать по всем символам всего текста
 RichEdit1.SelStart:=i;
 
// FillChar(CF, SizeOf(CF), 0);
// CF.cbSize:=SizeOf(CF);
// CF.dwMask:=CFM_OFFSET;
// CF.dwMask:=CFE_SUPERSCRIPT;
// RichEdit1.Perform(EM_GETCHARFORMAT, SCF_SELECTION, LPARAM(@CF));
 
FillChar(CF, SizeOf(CF), 0);
 
 if CF.dwMask = CFM_SUPERSCRIPT then        //Если текущий символ надстрочный, то...
 begin
  S1:=S1+RichEdit1.Text[i];                 //Все надстрочные символы в одну переменную
 end;
 
 if CF.yOffset <0 then                      //Если текущий символ подстрочный, то...
 begin
  S2:=S2+RichEdit1.Text[i];                 //Все подстрочные символы в одну переменную
 end;
 
end;
 
RichEdit2.Lines.Add('Надстрочные: '+S1);
RichEdit2.Lines.Add('Подстрочные: '+S2);
end;
Ответить с цитированием
  #2  
Старый 19.07.2021, 18:04
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,993
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Посмотри вот тут: https://supportcenter.devexpress.com...ipt-text-state
Может наведет на правильную мысль.
Ответить с цитированием
  #3  
Старый 20.07.2021, 13:55
Lighting Lighting вне форума
Прохожий
 
Регистрация: 18.07.2021
Сообщения: 5
Версия Delphi: Delphi 10.4
Репутация: 10
По умолчанию

Как же хреново быть тупым...
cxRichEdit (из того примера) это из библиотеки DevExpress VCL? А у меня ее нет. И Delphi 10.4 ругается на uses cxRichEditUtils;
Я пользовался RxLib, потом поставил JEDI (JvRichEdit - у него контекстное меню работает).
На торренте скачал DevExpress VCL v19.1.2 Full Sources for XE 10.4, но при установке (с помощью DxAutoInstaller) возникает миллион ошибок и результата нет.
Здесь еще нашел: https://github.com/search?q=DevExpress+VCL, но как скачать даже понять не могу. Библиотека больше гига должна быть, но такого нет.
Ответить с цитированием
  #4  
Старый 20.07.2021, 18:04
Lighting Lighting вне форума
Прохожий
 
Регистрация: 18.07.2021
Сообщения: 5
Версия Delphi: Delphi 10.4
Репутация: 10
По умолчанию

Скачал с официального сайта DevExpressVCL21.1.3 для 10.3Rio, Trial на 30 дней.
Компонент cxRichEdit появился, но есть ошибки: сначала с библиотекой RS26, пришлось указывать к ней путь (C:\Program Files (x86)\DevExpress\VCL\Library\RS26), потом ошибка такая: [dcc32 Fatal Error] E2202 Required package 'FireDAC' not found, и как ее исправить я не знаю.
Ответить с цитированием
  #5  
Старый 20.07.2021, 18:21
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,993
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Не ставить компоненты, связанные с данными. У тебя бесплатная версия Starter?

ЗЫ. Вообще-то я привел ссылку, где есть пример. Там в тексте один из разработчиков говорит, что их RichEdit это, как и большинство остальных, всего-лишь обертка для виндового контрола, т.е. должно работать в любом. Хотя там есть некоторая разница - надо смотреть какую версию виндового контрола использует конкретная библиотека. Вроде, начиная с W7, появилась версия 2.0. Стандартный контрол TRichEdit все еще опирается на 1.0 (вроде), но есть версии, которые уже работают с версией 2.0.

ЗЗЫ. Вот еще с другого форума:
Цитата:
you should be able to set sub/superscripts by sending an EM_SETCHARFORMAT
message to a TRichedit. Something like this:
Var
format: TCharFormat; { defined in Unit RichEdit }
FillChar( format, sizeof(format), 0);
With format Do Begin
cbSize:= Sizeof(format);
dwMask:= CFM_OFFSET;
yOffset:= 60;
{ superscript by 60 twips, negative values give subscripts}
End;
richedit1.Perform( EM_SETCHARFORMAT, SCF_SELECTION,
LongInt(@format));
The message affects the current selection. EM_GETCHARFORMAT can be used to
get the style set of the current selection into a TCharformat variable. You
check for sub/superscript by first testing
If (format.dwMask and CFM_OFFSET) <> 0 Then
...check format.yoffset for sign of offset
Note that richedit mark 1 (the version wrapped by Delphi's TRichedit) does
not automatically adjust the line spacing if you offset characters from the
baseline, and there is no way to change the line spacing from code. I don't
know if the newer richedit version 2.0 (there are wrappers on the Delphi
Super page, i think) handles this any better.
Тебе надо делать EM_GETCHARFORMAT и проверять что тебе напихали в соовт. структуру.
Ответить с цитированием
  #6  
Старый 20.07.2021, 20:23
Lighting Lighting вне форума
Прохожий
 
Регистрация: 18.07.2021
Сообщения: 5
Версия Delphi: Delphi 10.4
Репутация: 10
По умолчанию

Цитата:
Сообщение от lmikle
Не ставить компоненты, связанные с данными.
Я ничего такого не ставил. О чем речь?

Цитата:
Сообщение от lmikle
У тебя бесплатная версия Starter?
Starter это что?

Цитата:
Сообщение от lmikle
ЗЫ. Вообще-то я привел ссылку, где есть пример.
Да, я это все прочитал.
А мне вот такой совет показали: "Через EM_GETCHARFORMAT получить информацию о нужном символе в структуру CHARFORMAT (или CHARFORMAT2 для RE 2.0) и проверить содержимое поля yOffset. Если оно содержит нулевое значение - то текст обычный. Если положительное - текст надстрочный. Отрицательное - подстрочный."
Т.е. yOffset надо читать, а не писать в него. В вашем коде "yOffset:= 60; ", насколько я понял, для установки символа: над- или подстрочного, а значение 60 - смещение от центральной линии вверх.

А это пример, как узнать цвет слоя под текстом в RichEdit:
Код:
var
   CFormat : TCharFormat2;
begin
   FillChar(CFormat, SizeOf(CFormat), 0);
   CFormat.cbSize := SizeOf(cf);
   CFormat.dwMask := CFM_BACKCOLOR;
   RichEdit1.Perform(EM_GETCHARFORMAT, SCF_SELECTION, LPARAM(@CFormat));
   ShowMessage(ColorToString(CFormat.crBackColor));
end;

Насколько я понял, эта строка устанавливает параметры для вывода в RichEdit (если EM_SETCHARFORMAT)
Код:
richedit1.Perform( EM_SETCHARFORMAT, SCF_SELECTION, LongInt(@format));
Цитата:
Сообщение от lmikle
Тебе надо делать EM_GETCHARFORMAT и проверять что тебе напихали в соовт. структуру.
Да. Но как это сделать?
Я пробовал
Код:
CFormat.cbSize:=SizeOf(CFormat);
Код:
CFormat.dwMask:=CFM_SUPERSCRIPT;
Или
Код:
CFormat.dwMask:=CFM_OFFSET;
Код:
RichEdit1.Perform(EM_GETCHARFORMAT, SCF_SELECTION, LPARAM(@CFormat));
Потом
Код:
if CFormat.yOffset >0 then       //Если текущий символ надстрочный, то...
   begin
    S9:=S9+RichEdit1.Text[ii];   //Накапливаем все надстрочные символы в одну переменную
   end
но yOffset у меня постоянно = 0 вне зависимости от символа.
Значит, информация о нужном символе не передается в структуру CHARFORMAT2. Все примеры, что я видел или для выдачи символа в RichEdit или для получения информации из RichEdit куда указывает курсор. А у меня:
Код:
RichEdit1.SelStart:=i;
и все, дальше можно брать символ, например,
Код:
S4:=RichEdit1.Text[i];
а как его передать в CHARFORMAT2 я без понятия.

Я тут https://docs.microsoft.com/en-us/win...charformat2w_1 пытался что-нибудь выяснить, но это справочник какой-то для спецов, а мне нужен учебник, где бы было показано, что такое FillChar, cbSize, dwMask, Perform, что оно такое, и что туда писать.
Ответить с цитированием
  #7  
Старый 21.07.2021, 18:08
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,993
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

FillChar - заполняем память, выделенную для переменной указанным значением
cbSize - надо указать размер структуры, типа
Код:
CFormat.cbSize:=SizeOf(CFormat);
dwMask - код операции, которую надо выполнить
Perform - посылает сообщение (Windows message) окну компонента для обработки

Возможно, у тебя не работает, т.к. надо еше указать выделение. SelStart указвывает начало выделения, а SelLength - сколько выделено и оно у тебя равно 0. Есть мысль, что надо указывать там как минимум 1.
Ответить с цитированием
  #8  
Старый 23.07.2021, 15:26
Lighting Lighting вне форума
Прохожий
 
Регистрация: 18.07.2021
Сообщения: 5
Версия Delphi: Delphi 10.4
Репутация: 10
По умолчанию

Создал новый проект. Использую только стандартные TRichEdit, без всяких Jv, cx и пр.
Указываю RichEdit1.SelStart:=i; взять текущий символ, и RichEdit1.SelLength:=1; взять 1 символ. Хотя, если указать 3, то все равно берется только 1 символ. Почему - не пойму.
Непонятно, что нужно указывать в dwMask (хотя, пишут же для yOffset: Чтобы использовать этот элемент, установите флаг CFM_OFFSet в элементе DWMask, но я пробовал, а толку ноль). Пробовал разные варианты, но я не знаю главного - передается ли информация о нужном символе в структуру CHARFORMAT2. Что-то я не вижу, как бы он туда мог передаться. Где код, который за это отвечает?
Из Word'а копирую текст с над- и подстрочными символами и вставляю в RichEdit1.

Вот полный код:
Код:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, RichEdit;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    RichEdit2: TRichEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 RichEdit1.Clear;
 RichEdit2.Clear;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i:integer; S1,S2,S3,S4:string;
    CF:TCharFormat2;
begin
 for i:=1 to 5 do begin                   //Цикл идет от первого символа строки до последнего
 RichEdit1.SelStart:=i;                   //Установка начала выборки символов в строке
 RichEdit1.SelLength:=3;                  //Взять 1 символ

 S1:=RichEdit1.Text[i];                   //Текущий символ
 S2:=S2+RichEdit1.Text[i];                //Накапливаем все символы в одну переменную

 FillChar(CF, SizeOf(CF), 0);
 CF.cbSize:=SizeOf(CF);
 CF.dwMask:=CFM_SUPERSCRIPT;
// CF.dwMask:=CFE_SUPERSCRIPT;
// CF.dwMask:=CFM_OFFSET;
 RichEdit1.Perform(EM_GETCHARFORMAT, SCF_SELECTION, LPARAM(@CF));

 if CF.yOffset >0 then                    //Если текущий символ надстрочный, то...
  begin
  S3:=S3+RichEdit1.Text[i];               //Все надстрочные символы в одну переменную
  end;

 if CF.yOffset <0 then                    //Если текущий символ подстрочный, то...
  begin
  S4:=S4+RichEdit1.Text[i];               //Все подстрочные символы в одну переменную
  end;

 end;

 RichEdit2.Lines.Add('Надстрочные: '+S3);
 RichEdit2.Lines.Add('Подстрочные: '+S4);
end;
end.

Последний раз редактировалось Lighting, 24.07.2021 в 06:16.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 06:02.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter