Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Экранные координаты текстового курсора

2.1K
26 марта 2003 года
Murzilka
23 / / 23.12.2002
Экранные координаты текстового курсора - как их узнать?
Ситуация такая: хочу, что бы в RichEdit при нажатии определенного сочетания клавиш выскакивало окно (наподобии билдеровского для отображения членов класса, не помню как это называется - CodeGuard?), где предложены подходящие для данного слова окончания.
Создаю формочку, в нее запихиваю список, заполняю его, все хорошо, только вот где его (окно) отображать - не знаю :-/ Идея состояла в том, чтобы каким-либо образом узнать экранные координаты курсора в RichEdit, но не представляю, как это.
443
27 марта 2003 года
REmindER
292 / / 23.03.2003
Цитата:
Originally posted by Murzilka
Экранные координаты текстового курсора - как их узнать?
Ситуация такая: хочу, что бы в RichEdit при нажатии определенного сочетания клавиш выскакивало окно (наподобии билдеровского для отображения членов класса, не помню как это называется - CodeGuard?), где предложены подходящие для данного слова окончания.
Создаю формочку, в нее запихиваю список, заполняю его, все хорошо, только вот где его (окно) отображать - не знаю :-/ Идея состояла в том, чтобы каким-либо образом узнать экранные координаты курсора в RichEdit, но не представляю, как это.


Как ни странно, но довольно просто. Нужно воспользоваться API функцией GetCaretPos. Эта функция возвращает пиксельные координаты курсора в указанную структуру TPoint. Затем, конвертировать эти координаты в глобальные экранные, а потом глобальные экранные в систему координат нужного контрола. Это уж ты сам реши в какой. Делается это так:

TPoint XYPoint;

GetCaretPos(&XYPoint);
XYPoint = RichEdit1->ClientToScreen(XYPoint);
XYPoint = Form1->ScreenToClient(XYPoint);
//Т.е. сначала в глобальные координаты из RIchEdit'овских, а потом в оконные координаты Form1.

Вот и все. В XYPoint.x у тебя будет координата X, а в XYPoint.y - Y.

Кстати, если уж хочешь получить координаты курсора в Column и Row, то делай так:

XYPoint.y = SendMessage(RichEdit1->Handle, EM_LINEFROMCHAR, RichEdit1->SelStart,
0);
XYPoint.x = RichEdit1->SelStart - SendMessage(RichEdit1->Handle, EM_LINEINDEX,
XYPoint.y, 0);

Удачи.

2.1K
01 апреля 2003 года
Murzilka
23 / / 23.12.2002
Цитата:
Originally posted by REmindER

Кстати, если уж хочешь получить координаты курсора в Column и Row, то делай так:

XYPoint.y = SendMessage(RichEdit1->Handle, EM_LINEFROMCHAR, RichEdit1->SelStart,
0);
XYPoint.x = RichEdit1->SelStart - SendMessage(RichEdit1->Handle, EM_LINEINDEX,
XYPoint.y, 0);

Удачи.



Огромное спасибо.
По поводу процитированного мной:
в RichEdit есть свойство CaretPos типа TPoint, как я думал, показывающее координаты курсора строка/символ.. Есть их принципиальное отличие от получаемых посредством предложенного кода?

443
01 апреля 2003 года
REmindER
292 / / 23.03.2003
Цитата:
Originally posted by Murzilka


Огромное спасибо.
По поводу процитированного мной:
в RichEdit есть свойство CaretPos типа TPoint, как я думал, показывающее координаты курсора строка/символ.. Есть их принципиальное отличие от получаемых посредством предложенного кода?


Странно. Впервые о таком свойстве слышу. Ты уверен, что оно есть именно в RichEdit? Вообще, когда ссылаются на структуру TPoint, то подразумевают координаты пикселя, точки, но теоретически можно засунуть что угодно сходное.

2.1K
01 апреля 2003 года
Murzilka
23 / / 23.12.2002
Из хелпа 6го билдера (в 5м это св-во тоже есть)? свойсво TCustomMemo::CaretPos (ТRichEdit наследует от TCustomMemo):
__property TPoint CaretPos = {read=GetCaretPos, write=SetCaretPos};

Description

Use CaretPos to determine the coordinates of the cursor. TPoint type defines a pixel location onscreen, with the origin in the top left corner. X specifies the horizontal coordinate of the point, Y specifies the vertical coordinate. CaretPos indicates the X and Y position relative to the client origin of the memo.


Кстати, возникли еще вопросы, может, подскажете?
1 - Каким образом можно определить видимую часть текста в RichEdit? Т.е. вычислить, какие его строки отображаются на экране в данный момент?
2 - Можно ли изменять текст или шрифт текста в RichEdit без отображения изменений на экране? (Я имею ввиду нечто наподобии BeginUpdate и EndUpdate для TreeView)?
Ситуация такая: я раскрашиваю текст в RichEdit (т.е. допустим, IF окрашивается в синий цвет и тому подобное). Раскраска происходит путем анализа слова, на котором находится курсор, выделения этого слова (SelStart устанавливается на его начало, SelLength равняется его длине) и придания этому слову необходимого шрифта в зависимости от типа слова (SelAttributes->Font->Assert(нужный_шрифт)).
Это на самом деле выглядит просто ужасно. Если открывать какой-либо файл, объемом больший сотни килобайт, начинается мультик, слова поочереди выделяются, им присваивается какой-то шрифт, и так одно за другим... Каким образом можно решить такую проблему?
443
02 апреля 2003 года
REmindER
292 / / 23.03.2003
Цитата:
Originally posted by Murzilka
Из хелпа 6го билдера (в 5м это св-во тоже есть)? свойсво TCustomMemo::CaretPos (ТRichEdit наследует от TCustomMemo):
__property TPoint CaretPos = {read=GetCaretPos, write=SetCaretPos};

Description

Use CaretPos to determine the coordinates of the cursor. TPoint type defines a pixel location onscreen, with the origin in the top left corner. X specifies the horizontal coordinate of the point, Y specifies the vertical coordinate. CaretPos indicates the X and Y position relative to the client origin of the memo.


Кстати, возникли еще вопросы, может, подскажете?
1 - Каким образом можно определить видимую часть текста в RichEdit? Т.е. вычислить, какие его строки отображаются на экране в данный момент?
2 - Можно ли изменять текст или шрифт текста в RichEdit без отображения изменений на экране? (Я имею ввиду нечто наподобии BeginUpdate и EndUpdate для TreeView)?
Ситуация такая: я раскрашиваю текст в RichEdit (т.е. допустим, IF окрашивается в синий цвет и тому подобное). Раскраска происходит путем анализа слова, на котором находится курсор, выделения этого слова (SelStart устанавливается на его начало, SelLength равняется его длине) и придания этому слову необходимого шрифта в зависимости от типа слова (SelAttributes->Font->Assert(нужный_шрифт)).
Это на самом деле выглядит просто ужасно. Если открывать какой-либо файл, объемом больший сотни килобайт, начинается мультик, слова поочереди выделяются, им присваивается какой-то шрифт, и так одно за другим... Каким образом можно решить такую проблему?



Цитата:

Use CaretPos to determine the coordinates of the cursor. TPoint type defines a pixel location onscreen, with the origin in the top left corner. X specifies the horizontal coordinate of the point, Y specifies the vertical coordinate. CaretPos indicates the X and Y position relative to the client origin of the memo.



Как ты видишь сам, это и есть ответ на твой первый вопрос о пиксельном положении курсора.

1.
Можно узнать, отослав сообщение EM_CHARFROMPOS:

TPoint ControlPoint;

int TopLineIndex, BottomLineIndex;

ControlPoint.x = 0;
ControlPoint.y = 0;

TopLineIndex = SendMessage(RichEdit1->Handle, EM_LINEFROMCHAR, (WPARAM) SendMessage(RichEdit1->Handle, EM_CHARFROMPOS, 0, (LPARAM) &ControlPoint), 0);

ControlPoint.x = RichEdit1->ClientWidth - 1;
ControlPoint.y = RichEdir1->ClientHeight - 1;

BottomLineIndex = SendMessage(RichEdit1->Handle, EM_LINEFROMCHAR, (WPARAM) SendMessage(RichEdit1->Handle, EM_CHARFROMPOS, 0, (LPARAM) &ControlPoint), 0);

2.
Способ 1:
SendMessage(RichEdit1->Henadle, WM_SETREDRAW, false, 0);

Для отображения:

SendMessage(RichEdit1->Henadle, WM_SETREDRAW, true, 0);
RichEdit1->Invalidate();

Способ 2:
LockWindowUpdate(RichEdit1->Handle);

Для отображения:

LockWindowUpdate(NULL);

Второй способ даже предпочтительнее.

2.1K
03 апреля 2003 года
Murzilka
23 / / 23.12.2002
Опять огромное спасибо :)
Кстати, я снова поторопился и сам ответил на свой вопрос - для RichEdit->Lines описаны BeginUpdate и EndUpdate.

Естественно, появился еще один вопрос: каким образом можно установить курсор в нужную позицию? Для RichEdit не описана SetCaretPos, а вызов SetCaretPos APIшной (вроде бы это функция WinAPI такая?) не приводит к перемещению курсора в RichEdit.. (изменение SelStart не предлагать :) )
Неужто есть и на этот случай сообщения?
443
03 апреля 2003 года
REmindER
292 / / 23.03.2003
Цитата:
Originally posted by Murzilka
Опять огромное спасибо :)
Кстати, я снова поторопился и сам ответил на свой вопрос - для RichEdit->Lines описаны BeginUpdate и EndUpdate.

Естественно, появился еще один вопрос: каким образом можно установить курсор в нужную позицию? Для RichEdit не описана SetCaretPos, а вызов SetCaretPos APIшной (вроде бы это функция WinAPI такая?) не приводит к перемещению курсора в RichEdit.. (изменение SelStart не предлагать :) )
Неужто есть и на этот случай сообщения?


А почему тебе не нравится использование свойства SelStart? Ты не видишь установленного курсора, потому что ты делаешь эту установку, видимо, из другого контрола. А так как этот контрол был активен в момент установки, то он и останется активным после нее - будет иметь фокус ввода, значит никакого курсора в TRichEdit ты не увидишь. К примеру, это можно делать событием Click какой-то кпопки. Просто в конце установки позиции тебе нужно будет установить фокус на TRichEdit:

1.
Установка позиции курсора в координатах Row и Column:

RichEdit1->SelStart = 10;
RichEdit1->SelLength = 0;
RichEdit1->SetFocus();

Здесь еще бы желательно добавить SendMessage(RichEdit1->Handle, EM_SCROLLCARET, 0, 0);. Это для того, чтобы курсор не "ускакал" за пределы TRichEdit'а вверх или вниз. Т.е. это сообщение "перемотает" контрол на позицию курсора.

2.
Установка позиции курсора по приблизительным пиксельным координатам внутри клиентской зоны:

RichEdit1->SetFocus();
SetCaretPos(5, 5);

2.1K
03 апреля 2003 года
Murzilka
23 / / 23.12.2002
Цитата:
Originally posted by REmindER

А почему тебе не нравится использование свойства SelStart?



Честно говоря, с этим у меня проблема примерно такая: при включенном переносе слова имеем, допустим, три строки текста (на экране) и две фактических строки. Т.е. первая строка больше отображаемой области RichEdit и потому перенесена, в то время как сама RichEdit->Lines->Strings[X] по прежнему осталось одной, не была разбита.
И вот допустим, мне надо курсор установить на начало второй (фактической, т.е. той, которая третья :) ) строки. В этом случае еще бороться можно - узнать длину первой строки, прибавить к ней 2... Бороться можно, но как-то это криво кажется :-/
И другая ситуация - курсор находится в позиции Х. Мне хочется знать, какая же это строка в RichEdit->Lines (ее индекс в StringList, то есть). Опять организовывать цикл, считать количество символов с первой строки до текущей...? Тоже можно, конечно, но опять как-то хитрозамороченно кажется :(

443
04 апреля 2003 года
REmindER
292 / / 23.03.2003
Цитата:
Originally posted by Murzilka


Честно говоря, с этим у меня проблема примерно такая: при включенном переносе слова имеем, допустим, три строки текста (на экране) и две фактических строки. Т.е. первая строка больше отображаемой области RichEdit и потому перенесена, в то время как сама RichEdit->Lines->Strings[X] по прежнему осталось одной, не была разбита.
И вот допустим, мне надо курсор установить на начало второй (фактической, т.е. той, которая третья :) ) строки. В этом случае еще бороться можно - узнать длину первой строки, прибавить к ней 2... Бороться можно, но как-то это криво кажется :-/


Прости, но я себе что-то не представляю такую ситуацию, где нужно было бы устанавливать курсор принудительно.

Цитата:

И другая ситуация - курсор находится в позиции Х. Мне хочется знать, какая же это строка в RichEdit->Lines (ее индекс в StringList, то есть). Опять организовывать цикл, считать количество символов с первой строки до текущей...? Тоже можно, конечно, но опять как-то хитрозамороченно кажется :(


Я же объяснял как узнать глобальный индекс символа в TRichEdit по координатам, а затем по нему вычислить номер строки.

2.1K
05 апреля 2003 года
Murzilka
23 / / 23.12.2002
Цитата:
Originally posted by REmindER

Прости, но я себе что-то не представляю такую ситуацию, где нужно было бы устанавливать курсор принудительно.



Раскраска текста.

Цитата:
Originally posted by REmindER
Я же объяснял как узнать глобальный индекс символа в TRichEdit по координатам, а затем по нему вычислить номер строки.


Это же будет номер строки на экране, не номер ее в RichEdit->Lines->Strings

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог