Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Статус
Закрыто для дальнейших ответов.

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Corel Draw X3.
Задача следующая. Имеется тесктовый об_ект ArtisticText. Пользователь переходит в режим редактирования и выделяет один или несколько подряд идущих символов (все выделяемые символы находятся в одной строке). Далее жмёт волшебную кнопку и над этими символами появляется стрелка.
Вариант с символами, которые в своём составе уже имеют стрелки, отметаю, поскольку стрелка может быть как над одним символом, так и над несколькими (в последнем случае длина стрелки будет равна ширине выделенных символов), т.е. стрелка не может быть связана с одним символом. Остаётся вариант, когда стрелка создаётся в определённой позиции (над выделенными символами) как самостоятельный об_ект, т.е. кривая с наконечником.

При этом возникают такие вопросы:
1. Как определить позицию выделенного символа (выделенных символов) в составе ArtisticText ?
2. Как определить ширину и высоту, занимаемую выделенными символами в составе ArtisticText ?
3. Как отлавливать событие, когда в режиме редактирования удаляется или создаётся символ ? Это нужно для того, чтобы автоматически (синхронно с редактированием текста) изменять длину стрелки или удалять её.

P.S. А может, это вообще не реализуемо на уровне макросов ?
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

По-моему, никак. Можно только получить выделеные символы, а их местонахождение на экране или внутри текста закрыто. :(
Text.Selection.Start, Text.Selection.End - относительная позиция выделеных символов в тексте.
 

Fog_patch

12 лет на форуме
Сообщения
3 163
Реакции
998
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Это можно сделать, но через WinAPI. И придется углубиться в метрики шрифтов.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Это можно сделать, но через WinAPI. И придется углубиться в метрики шрифтов.
Вы черезчур оптимистичны. Подумайте, как можно через метрики шрифтов определить позицию отдельного символа внутри кореловского фрейма? Смоделировать, как GDI сам отрисовал бы этот текст? Или, разве что, каким-то умопомрачительным хакерским способом через API влезть в кореловскую библиотеку прорисовки текста (кажется CDRTXT.DLL) и посмотреть, куда она какой символ поставила?
 

Fog_patch

12 лет на форуме
Сообщения
3 163
Реакции
998
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Этот оптимизм с допуском точности. Чем больше вложишь в алгоритм, тем точнее. Но, думаю, даже без сверхъестественных усилий можно достаточно точно определить положение символа во фрейме. Для практических целей подойдет, а для академических нужно будет копать очень глубоко.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Да не пойдет однозначно. Вы же не знаете, сколько внутри фрейма текста, какая выключка, как его масштабировали, сдвигали, и т.д.
Для одного небольшого слова набранного стандартным шрифтом, какой-то допуск и будет, но для нескольких слов и, тем более, строк, вы кореловскую отрисовку через GDI не сэмулируете никак. Единственно что, мне в голову сейчас пришло, можно текст на время в кривые перевести и по буквам разобрать, определить позицию каждой, а потом обратно вернуть. Но это, как понимаете, все равно закат солнца в ручную. К тому же, как я понял, ТС еще сам не определился, надо ли это ему и что, вообще, надо. ;-)
 

Fog_patch

12 лет на форуме
Сообщения
3 163
Реакции
998
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Подойдет. Я для иллюстратора пару лет назад писал какую-то примочку, которая определяла положение символа. Что значит не знаю? В Кореле, что, нельзя программно определить параметры текста, выключки, кернинга?
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Можно, но программно через API вы текст с этими параметрами не отрисуете.
А что, в иллюстраторе, разве нет доступа к координатам символа внутри фрейма?

Кстати, есть еще более здравая идея!
1)Сперва запомнить исходный текст.
2)Если текст из нескольких строк - Break Artistic Text Appart - получим массив отдельных объектов-строк
3)Внутри каждой строки опять Break Artistic Text Appart - получим массив отдельных объектов-слов
4)Внутри каждого слова опять Break Artistic Text Appart - получим массив отдельных объектов-букв.
5)Для каждого объекта-буквы заполняем массив координат
6)Возвращаем исходный текст обратно

И не надо никаких извратов с API и управлением стрелками десятком кнопочек
:D
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Отличный вариант.
Только вот не пойму я, как массив полученных частей получить. В справке написано, что BreakApartEx возвращает ShapeRange. Но фактически возвращает массив из одного Shape'а - первой части. Т.е. ссылки на остальные получившиеся части теряются.

Set numberArray = numberCopy.BreakApartEx
MsgBox numberArray.count // 1


P.S. Как вариант - предварительно группировать с чем нибудь разделяемый на части текст. В этом случае после разделения текста все его части окажутся в этой группе.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Да, есть такая беда, более того, после BreakArtisticText выделение тоже перескакивает на первый разгруппированный объект. Видимо, придется все объекты внутри исходного фрейма перебирать справа-налево сверху-вниз, благо не должны пересекаться.
 

Asmussen

15 лет на форуме
Сообщения
143
Реакции
47
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

На всякий случай - после Break Appart слетит выравнивание текста Full
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

И это не единственный подводный камень.
Какие-то допущения все равно должны быть. Для большей достоверности, можно, как я первоначально предлагал, в кривые переводить, но тогда придется достаточно сложно ковыряться в разборке SubPathов.
 

Asmussen

15 лет на форуме
Сообщения
143
Реакции
47
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

В копилку еще дедовский способ окривления. Если при экспорте в EPS выбрать экспортировать текст как кривые, по импорте его обратно получим окривленный текст посимвольно. Правда я не помню, можно ли это проделать через VBA
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

после BreakArtisticText выделение тоже перескакивает на первый разгруппированный объект
Так BreakArtisticText - это и есть BreakApart.
А то, что на первый перескакивает - вполне логично (но если бы выделенными оставались все части, то их можно было бы получить из ActiveSelectionRange). Плохо то, что функция BreakApartEx не возвращает массив частей.

Видимо, придется все объекты внутри исходного фрейма перебирать справа-налево сверху-вниз, благо не должны пересекаться.
А если там другой мелкий текст окажется ?

Какие-то допущения все равно должны быть.
Какие допущения ? Все части на своих местах остаются.

------------------------------------------------------------
Всё-таки разбивку на части лучше сделать так:

PHP:
Function BreakArtisticText(shp As shape) As shape
    Dim shpCopy As New shape
    Dim shpGroup As New shape
    Dim shpArray As New ShapeRange

    Set shpCopy = shp.Duplicate()
    shpArray.Add shp
    shpArray.Add shpCopy
    Set shpGroup = shpArray.Group
    shp.BreakApart
    shpCopy.Delete
    Set BreakArtisticText = shpGroup
End Function

На всякий случай - после Break Appart слетит выравнивание текста Full
А вот здесь алгоритм, предложенный _MBK_, слажает ))
Впрочем, выравнивание по ширине мы не используем.
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Ещё один момент. После удаления 10-х и 13-х символов из фрагментов текста, полученных после BreakApart, получаем следующую картину:
Для всех полученных фрагментов Функция Text.Story.Length возвращает на 1 символ больше (врёт), чем функция Len(Text.Story).
Почему - так и не понял. т.к. последнего символа фактически не существует (выделял функцией Mid - получаю строку нулевой длины).
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Text.Story.Length всегда для любого текстового фрагмента на один больше количества символов. Я так понимаю, нулевой символ в конце считается или символ-счетчик в начале.
А какая вам разница? Принять как данность и все.
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Я так понимаю, нулевой символ в конце считается или символ-счетчик в начале.
Этот "символ" находится в самом конце. Возможно, нулевой символ (Text.Replace его не "видит").
А вообще, нелогично работает метод Text.Story.Length, если там действительно нулевой символ. Если какой-то другой, то, возможно, и оправданно.
Впрочем, получить его asci-код у меня не получилось.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Не пойму, что нелогичного? Никого ж не возмущает, что в C++ или в паскале для хранения строковой переменной из N символов нужно N+1 байт и sizeof от этой переменной тоже вернет N+1
 

Cyrax

Топикстартер
10 лет на форуме
Сообщения
588
Реакции
4
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

Никого ж не возмущает, что в C++ или в паскале для хранения строковой переменной из N символов нужно N+1 байт
Тем не менее, функции strlen (С++) и length (Паскаль) возвращают N, а не N+1.

sizeof от этой переменной тоже вернет N+1
Функция "sizeof" имеет отношение к физическому представлению данных, Text.Story.Length - к логическому. Например, в Delphi и BCB метод AnsiString.Length возвращает N символов, а не N+1. Да и Text.Story как об_ект класса TextRange физически занимает в памяти больше байт, чем N+1.
 

_MBK_

Пикирующий бомбардировщик
15 лет на форуме
Сообщения
33 137
Реакции
10 835
Ответ: Определение позиции и ширины одного или нескольких символов внутри ArtisticText

На самом деле объект класса TextRange - это не строковая переменная, соответственно и метод (или свойство?) Length имеет, скорее, физический смысл, а не означает длину строки, хранящейся внутри него. К примеру, если строковой переменной присвоить то, что внутри этого объекта находится, а потом длину строки вернуть, то все будет как надо.
 
Статус
Закрыто для дальнейших ответов.