Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.04.01;
Скачать: CL | DM;

Вниз

Рисование в RichEdit   Найти похожие ветки 

 
Andr-04   (2006-07-08 19:48) [0]

Никак не могу корректно обновлять нарисованное в RichEdit через Canvas! При обрабатывании OnPaint (не важно как - и через OnMessage, и через своё событие) нарисованный фрагмент при прокручивании размножается, а если отлавливать прокрутку, то перерисовка происходит не всегда, да и на границе остаются следы рисунка. Если у кого есть опыт в данной области, какие именно события нужно отлавливать, какие сообщения нужно отправлять при их обработке и т.д. поделитесь, пожалуйста!


 
KilkennyCat ©   (2006-07-09 02:40) [1]

Посмотрите пример у RxLib, там вроде бы, было.


 
KilkennyCat ©   (2006-07-09 02:41) [2]

прошу прощения, не заметил, что - KOL...


 
Andr-04   (2006-07-10 15:02) [3]

Поскольку больше никто ничего не советует, решил посмотреть RxLib, но что-то связанное с рисованием мне там найти не удалось. Подскажите, пожалуйста, как воспользоваться RxRichEdit для рисования на нём. Вообще, мне нужно всего-навсего нарисовать рамку, внутри которой необходимо будет изменять текст, а уже правее неё должен следовать неизменяемый текст (ну, предотвратить изменение изменяемого проще простого). Пробовал использовать таблицу из 1 строки и 1 столбца, но правее неё разместить ничего не удалось, а при создании таблицы из 1 строки и 2 столбцов не удалось скрыть границы второй ячейки. Жду предложений.


 
Unknown Mystic ©   (2006-07-10 18:12) [4]

А как советовать, если ничего не понятно?.. Привел бы минимальный код что ли...

А ты его вообще отчищаешь перед тем как поновой рисовать то?


 
Andr-04   (2006-07-11 18:04) [5]

А зачем очищать-то? Пусть на нарисованном рисуется! Боюсь, конечно, выглядеть идиотом, но всё-таки рискну привести свой код (это не конечный, а предварительный. На нём вместо прямоугольника рисуется простой отрезок. Но суть от этого не меняется)! :-)
function TForm1.RichEdit1Message(var Msg: tagMSG;
 var Rslt: Integer): Boolean;
var
 x, y: Integer;
begin
 if msg.message=wm_paint then
   begin
     x:=GetScrollPos(RichEdit1.Handle, SB_HORZ);
     y:=GetScrollPos(RichEdit1.Handle, SB_VERT);
     RichEdit1.Canvas.Rectangle(33-x, 20-y, 88-x, 50-y);
   end;
 result:=false;
end;

Причём я ещё не затрагиваю проблему белого фона внутри прямоугольника - думаю, в карайнем случае отрезками нарисую, т.к. BrushStyle тоже не помогает.
Для испытания моего кода необходимо предварительно в RichEdit "забить" мусор.


 
Andr-04   (2006-07-11 18:08) [6]


> На нём вместо прямоугольника рисуется простой отрезок. Но
> суть от этого не меняется

Уже подправил перед отправлением поста, но убрать в сообщении эту реплику забыл.


 
Andr-04   (2006-07-12 16:38) [7]

Ура, понял почему так происходит! Дело в том, что при перемещении ползунка полосы прокрутки кнопкой мыши до её отпускания GetScrollPos выдаёт начальное положение полос прокрутки, с которого она началась. GetScrollInfo тоже ничего корректного не выводит (возможно, не правильно выставляю параметр fMask (я устанавливаю его в SIF_POS)). Если я иду не в том направлении - поправьте, если в том - подскажите что нужно изменить. Все примеры рисования, которые я находил в интернете, не расчитыны на перемещение нарисованного при прокрутке RichEdit. Поэтому решение этого вопроса будет полезно и не только при KOL-программировании.


 
Unknown Mystic ©   (2006-07-12 21:21) [8]

В общем так, с графикой я не работал, так что мало что могу подсказать...

Но помоему мое предположение верно - "размножение" происходит из-за того, что ты не удаляешь то, что до этого рисовал. И вообще что-то страшное ты замутил с высчитыванием того, не ясно чего :)

Замени обработчик wm_paint на вот это и посмотри что будет...
    RichEdit1.Canvas.FillRect(RichEdit1.Canvas.ClipRect());
    RichEdit1.Canvas.Rectangle(33, 20, 88, 50);

Конечно не особо, но во всяком случае прямоугольник не плодится ;)


 
Andr-04   (2006-07-12 21:36) [9]

Не, мне нужно чтобы это нарисованное изображение не сидело фоном, а тоже, вместе с текстом, ПЕРЕМЕЩАЛОСЬ!


 
Unknown Mystic ©   (2006-07-13 03:15) [10]

Ааа... Теперь понял :)

Ну тогда что-то вроде:
function TForm1.RichEdit1Message(var Msg: tagMSG;
 var Rslt: Integer): Boolean;
var
 SI: TScrollInfo;
 x, y: Integer;
begin
 if msg.message = WM_PAINT then
 begin
   x := 0;
   y := 0;

   FillChar(SI, SizeOf(SI), 0);
   SI.cbSize := SizeOf(SI);
   SI.fMask := SIF_RANGE or SIF_POS or SIF_TRACKPOS or SIF_PAGE;
   GetScrollInfo(RichEdit1.Handle, SB_VERT, SI);

   EditBox2.Text := Int2Str(SI.nPos);
   EditBox3.Text := Int2Str(SI.nTrackPos);
   if SI.nTrackPos = 0 then y := SI.nPos
   else y := SI.nTrackPos;
   RichEdit1.Canvas.Rectangle(50 - x, 50 - y, 150 - x, 150 - y);
 end;
 Result := FALSE;
end;


Правда в маске может что-то лишнее - не разбирался. Это первое, что я в KOL.PAS нашел - лениво самому SI заполнять было :))


 
Andr-04   (2006-07-13 10:34) [11]

Да, получилось, но всё равно очень часто случаются случаи и размножения, и съезжания рисунка (например, после опускания из самого верхнего положения кнопкой "вниз" полосы и поднятия ползунком). Я даже пытался перехватывать wm_vscroll и, в зависимости от метода прокрутки (ползунком, стрелочкой или пространством между ползунком и стрелочкой) выставлял текущее значение y - ничего не помогло. Вот примерно то, что у меня сейчас:
var
 y: Integer;
 SI: TScrollInfo;
begin
 if (msg.message=wm_paint) or (msg.message=wm_vscroll) then
   begin
     GetScrollInfo( RichEdit1.Handle, SB_VERT, SI );
     if msg.message=wm_vscroll then
       if LoWord(Msg.wParam)=SB_THUMBTRACK then
         y:=si.nTrackPos
       else
         y:=si.nPos
     else
       if SI.nTrackPos = 0 then
         y := SI.nPos
       else
         y := SI.nTrackPos;
     RichEdit1.Canvas.MoveTo(33, 20-y);
     RichEdit1.Canvas.LineTo(88, 20-y);
     RichEdit1.Canvas.LineTo(88, 50-y);
     RichEdit1.Canvas.LineTo(33, 50-y);
     RichEdit1.Canvas.LineTo(33, 20-y);
   end;
 result:=false;
end;

Да, ещё замечу, что даже если обрабатывать исключительно все события, а не только wm_paint, то всё равно прорисовка прямоугольника иногда не срабатывает! Возможно можно попробовать в сам RichEdit помещать компоненты (это возможно), но, помню, когда-то экспериментировал - и всё равно прорисовка страдала! Вот так загадка!..


 
Unknown Mystic ©   (2006-07-14 00:40) [12]

Так... Посмотрел еще малость.

Двоение в приведенном тобой примере - думается результат не совсем корректной проверки:
if SI.nTrackPos = 0 then y := SI.nPos
  else y := SI.nTrackPos;


Надо по нормальному вытаскивать прокручивается ли окно за ползунок или нет.

Ну и второе - это при вводе строк, которые пересекают рисунок...


 
Andr-04   (2006-07-14 11:33) [13]

Да, я уже ещё малость переделал - заметил ещё, что при опускании на самый низ nTrackPos возвращает величину на 1 больше максимальной. Это тоже исправил. И перерисовку сделал на любое событие OnMessage кроме wm_vscroll, но всё равно замечаются случаи недорисованности (ненарисованности) (например, если отвести ползунок вниз, а затем, не отпуская кнопку мыши, увести курсор очень далеко от полосы прокрутки, чтобы полоса вернулась на прежнее состояние). Если же wm_vscroll тоже обрабатывать, то прямоугольник будет размножаться, хотя случай, описанный в скобках выше, в таком случае определяется, но прямоугольник рисуется до прокрутки, из-за чего его всё равно не видно. Вот что у меня сейчас:
var
 cscr: Integer = 0;
function TForm1.RichEdit1Message(var Msg: tagMSG;
 var Rslt: Integer): Boolean;
var
 y: Integer;
 SI: TScrollInfo;
begin
 if msg.message=wm_vscroll then
   cscr:=LoWord(Msg.wParam)
 else
   begin
     SI.cbSize := Sizeof( SI );
     SI.fMask := SIF_POS or SIF_RANGE or SIF_TRACKPOS or SIF_PAGE;
     GetScrollInfo( RichEdit1.Handle, SB_VERT, SI );
     if cscr=SB_THUMBTRACK then
       y := SI.nTrackPos
     else
       y := SI.nPos;
     if y>si.nMax-si.nPage then
       y:=si.nMax-si.nPage;
     RichEdit1.Canvas.Pen.Color:=clBlack;
     RichEdit1.Canvas.MoveTo(33, 20-y);
     RichEdit1.Canvas.LineTo(88, 20-y);
     RichEdit1.Canvas.LineTo(88, 50-y);
     RichEdit1.Canvas.LineTo(33, 50-y);
     RichEdit1.Canvas.LineTo(33, 20-y);
     RichEdit1.Canvas.Pen.Color:=RichEdit1.Color;
     RichEdit1.Canvas.MoveTo(0, 0);
     RichEdit1.Canvas.LineTo(RichEdit1.ClientWidth, 0); //это чтобы на самой верхней линии RichEdit не оставались следы от нарисованного прямоугольника
   end;
 result:=false;
end;


 
Unknown Mystic ©   (2006-07-15 23:48) [14]

Не знаю из-за чего оно не отрисовывается, но при этом сообщение WM_PAINT посылается и отлавливается...


 
Andr-04   (2006-07-20 22:04) [15]

Прошу прощения, что не писал - уезжал из дома. Да, WM_PAINT тоже отлавливается, но НЕ при уводе курсора во время перемещения ползунка прокрутки на большое расстояние от самой полосы. В такой момент WM_PAINT не отлавливается, и не знаю почему. А как быть на счёт добавления runtime компонентов непосредственно в RichEdit? Может там возможно как-то сделать корректную отрисовку? Я уже давно этот эксперимент проводил, поэтому у меня ничего не сохранилось. Я тогда CheckBox помещал... Помню только что он корректно перемещался, но тоже рзмножался... Может кому-нибудь удастся добиться каких-нибудь результатов? Если конкретно - нужно будет в различных условиях помещать либо EditBox, либо CheckBox, либо RadioBox (с определением ситуации когда помещать каждый проблем нет - просто необходимо проверить перечисленные 3 случая). Тут ещё на ум приходит плагин Миранды (альтернативный ICQ клиент), вроде Scriver.dll называется... В нём в качестве истории сеанса переписки используется RichEdit, где каждое сообщение можно разделять горизонтальной полосой, которая перерисовывается корректно. Думал, что это специфическая RTF-команда, но когда при помощи WinHex посмотрел содержимое памяти приложения, ничего специфического не обнаружил. Следовательно, это либо runtime-компоненты, либо обработка прорисовки.


 
homm ©   (2006-07-20 23:59) [16]

> [15] Andr-04   (20.07.06 22:04)

в qip во время запроса авторизации у пользователя, у которого спрашивают авторизации, появляются 2 кнопки: соответственно принять и отказатся. (уж не знаю как эта информация поможет, но...  :) )


 
Andr-04   (2006-07-21 19:28) [17]


> в qip во время запроса авторизации у пользователя, у которого
> спрашивают авторизации, появляются 2 кнопки: соответственно
> принять и отказатся. (уж не знаю как эта информация поможет,
>  но...  :) )

Да уж... Действитльно кроме ":)" ничего не скажешь... Но тут у нас, извините, не каламбур! И по этому прошу отвечать строго по теме! Плагин Scriver от Mirand"ы имеет к этому отношение - его делали люди на основе RichEdit, и им удалось сделать корректную прорисовку. Вопрос: каким образом? А две кнопочки и в Mirand"е появляются... Это не удивительно, а логично!


 
AndreyRus   (2006-07-22 00:03) [18]

Да уж... Действитльно кроме ":)" ничего не скажешь...
Аааа! :)
Homm не проснулся!


 
Andr-04   (2006-07-22 10:01) [19]

Ну пусть тогда просыпается и подключается к решению задачи! Подключайтесь все! :-) И давайте без флуда! Без этого уже не мало написано, хотя бывает и намного больше...


 
Andr-04   (2006-07-22 10:04) [20]

И пишу в основном я... :-)


 
homm ©   (2006-07-22 13:57) [21]


> Homm не проснулся!

В qip тоже RichEdit используется :P


 
homm ©   (2006-07-22 13:59) [22]

а еще он написан на дельфи. А еще автор рускоязычный. Может к нему на мыло обрариться?

ЗЫ Чесное слово, мне бы тоже было интересно решение, но у меня нет времени, так что сори :)


 
Andr-04   (2006-07-22 20:15) [23]


> В qip тоже RichEdit используется :P

Не могли бы подсказать в каком именно месте? Специально только что скачал новую с офф. сайта - там везде TRichView - и в истории, и в окне переписки... А RichView и RichEdit - далеко не одно и тоже!
P.S. Но если бы не этот случай, ещё не знаю когда бы этот QIP увидел в глаза...
Так что плагин Scriver.dll от Mirand"ы остаётся в силе!


 
AndreyRus   (2006-07-24 05:14) [24]


>RichView и RichEdit - далеко не одно и тоже!

А что такое - RichView?


 
Unknown Mystic ©   (2006-07-24 12:37) [25]


> Да, WM_PAINT тоже отлавливается, но НЕ при уводе курсора
> во время перемещения ползунка прокрутки на большое расстояние
> от самой полосы.

Ты уверен? Я так понял имеется ввиду момент, когда при отводе курсора на большое расстояние, ползунок из некоторого положения перескакивает в начало.
Так вот, если не ошибаюсь, в этом случае WM_PAINT проходит... Попробуй в его обработчик этого события поставить инкремент значения какого-нибудь эдита...


 
Andr-04   (2006-07-24 15:11) [26]


> Ты уверен? Я так понял имеется ввиду момент, когда при отводе
> курсора на большое расстояние, ползунок из некоторого положения
> перескакивает в начало.
> Так вот, если не ошибаюсь, в этом случае WM_PAINT проходит.
> .. Попробуй в его обработчик этого события поставить инкремент
> значения какого-нибудь эдита...

Вот именно, что WM_PAINT не происходит в этом случае! Уверен на 99% (1% - резерв ;-) )! Проверьте собственноручно мой код в 13-м посте и убедитесь в этом сами!


> А что такое - RichView?

А RichView - это набор компонент для работы с RTF, только с дополнительными (даже по сравнению с RxRichEdit) наворотами. Но он платный, и существует только для VCL, т.е. для собравшейся здесь публики он ни коем образом не пригоден. К тому же, у меня есть подозрение, что он полностью написан с нуля, поэтому и переделывать его на KOL нет никакого смысла. Яркий пример его использования, как я уже говорил - это QIP. Но лично мне он не понравился! :-)

Также я успел 22.07.2006г. написать письмо разработчикам Scriver.dll с просьбой помочь мне, но ответ они писать пока упорно не хотят! :-(


 
Unknown Mystic ©   (2006-07-25 02:19) [27]

Могу только повторить то, что уже сказал перед этим. Только уже без "если не ошибаюсь" - только что еще раз проверил...


 
Andr-04   (2006-07-25 11:30) [28]

Да как это прорисовывается!? Только что ещё раз специально проверил - прямоугольник рисуется только ПОСЛЕ отпускания кнопки мыши! Это нужно исключить! Нужно чтобы прямоугольник рисовался сразу после возврата к началу, а не после того как ещё мышку отпустишь! Приведите, пожалуйста Ваш код, а проверьте мой из поста №13.


 
Unknown Mystic ©   (2006-07-25 13:07) [29]

Я не говорил что прорисовывается! Я сказал, что WM_PAINT проходит. (см. 14, а также 25 и 27)


 
Andr-04   (2006-07-25 21:00) [30]

И какой тогда толк от WM_PAINT? Мне кажется, здесь нужен немного другой подход, который мне найти так и не удалось! Пожалуйста, кто может, подскажите!



Страницы: 1 вся ветка

Текущий архив: 2007.04.01;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.049 c
2-1173179877
Marat
2007-03-06 14:17
2007.04.01
читаю файл


15-1172656454
IMHO
2007-02-28 12:54
2007.04.01
Зенит купил Тимощука за 20 миллионов долларов!!!


2-1173223246
Gelikon
2007-03-07 02:20
2007.04.01
Как заставить Panel мигать через определённый интервал времени!!!


3-1168866075
Галинка
2007-01-15 16:01
2007.04.01
DataSet записать в физическую базу


2-1173176996
Tar
2007-03-06 13:29
2007.04.01
Множества