Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2015.09.10;
Скачать: [xml.tar.bz2];

Вниз

Своя отрисовка TMemo   Найти похожие ветки 

 
Alex_C   (2014-03-14 11:25) [0]

Столкнулся с такой проблемой:
нужно создать свой TMemo с подсветкой синтаксиса.
Вроде как не проблема. Делаю так:


 TMyMemo = class(TCustomMemo)
 ...
   procedure WMPaint(var message: TWMPaint); message WM_PAINT;

var
 FImage: TBitMap;

procedure TMyMemo.WMPaint(var Message: TWMPaint);

begin
 DC := Message.DC;
 if DC = 0 then
   DC := BeginPaint(Handle, PS);
 try
   FImage.Handle := CreateCompatibleBitmap(DC, Width, Height);
   тут рисую на FImage то что надо

   BitBlt(DC, 0, 0, FImage.Width, FImage.Height, FImage.Canvas.Handle,
     0, 0, SRCCOPY);
 finally
   if Message.DC = 0 then
     EndPaint(Handle, PS);
 end;
end;


Однако при постоянной отрисовке своего мемо заметил мерцание, которого при BitBlt быть не должно. При пошаговой трассировке выяснилось, что мое мемо сначала отрисовывается как стандартное мемо, а вот потом происходит отрисовка по моему событию.
Вопрос: в каком месте происходит эта стандартная отрисовка и как ее отменить.


 
clickmaker ©   (2014-03-14 11:35) [1]

а принципиально мемо? есть ведь SynEdit с пачкой готовых подсветчиков.
Если по теме - то вроде как надо в WM_ERASEBKGND возвращать не ноль, говоря винде, что ты сам рисуешь фон


 
Alex_C   (2014-03-14 11:56) [2]

Да про SynEdit знаю, но мне своя специфика нужна.
На счет WM_ERASEBKGND - это есть


procedure TMyMemo.WMEraseBkgnd(var Msg: TMessage);
begin
 Msg.Result := 1;
end;


Но все равно есть мерцание - т.е. винда все равно сама рисует фон.


 
Alex_C   (2014-03-14 12:11) [3]

В дополнение к этому: я нашел в какой момент идет стандартная отрисовка:

У меня есть такой код

   while MyMemo.Lines.Count >= 50 do      
     MyMemo.Lines.Delete(0);                    <- вот тут идет стандартная отрисовка
   MyMemo.Text := MyMemo.Text + TextOut;
   MyMemo.SelStart := Length(MyMemo.Text);


 
Игорь Шевченко ©   (2014-03-14 12:12) [4]

еще как минимум WM_CTLCOLOREDIT (CN_CTLCOLOREDIT)


 
Юрий Зотов ©   (2014-03-14 12:17) [5]

Не в BeginUpdate ли тут дело?

with MyMemo.Lines do
begin
 BeginUpdate;
 try
   while Count >= 50 do      
     Delete(0);
 finally
   EndUpdate
 end
end;


 
Alex_C   (2014-03-14 12:41) [6]

BeginUpdate/EndUpdate - да дело действительно в этом. Но почему без них вызывается не мой метод Paint, а стандартный виндовый?


 
Юрий Зотов ©   (2014-03-14 13:19) [7]

> Alex_C   (14.03.14 12:41) [6]
> почему без них вызывается не мой метод Paint, а стандартный виндовый?

Надо смотреть, что происходит внутри EndUpdate. Возможно, вместо посылки WM_PAINT там идет принудительная отрисовка, поэтому до Вашего перехватчика дело не доходит. И если так, то этим кодом мы просто свели многократную стандартную отрисовку к однократной, вот оно и не моргает.


 
Юрий Зотов ©   (2014-03-14 13:20) [8]

Удалено модератором
Примечание: Дубль


 
Alex_C   (2014-03-21 17:59) [9]

Как выяснилось, что написал Юрий Зотов - правда)))
Нужно


procedure TMyMemo.CNCommand(var Message: TWMCommand);
begin
 if (Message.NotifyCode = EN_CHANGE) then
   // Для перерисовки при изменении текста
 begin
   if Assigned(FOnChange) then FOnChange(Self);
   //inherited; //<- не вызываем, рисуем сами!
   Refresh;
 end;
end;


обрабатывать самому EN_CHANGE.

Теперь следующая проблема: TWMHScroll


procedure TMyMemo.WMHScroll(var Message: TWMHScroll);
var
 Position, HMin, HMax: integer;
 SI: TScrollInfo;
 CaretP: integer;
begin
//  inherited;
 CaretP := GetCaretPosFromXY(CaretPos);
 GetScrollRange(Handle, SB_HORZ, HMin, HMax);
 Position := GetScrollPos(Handle, SB_HORZ);
 with Message do
   case ScrollCode of
     SB_LINELEFT: SetScrollPos(Handle, SB_HORZ, Position - 1, True);
     SB_LINERIGHT: SetScrollPos(Handle, SB_HORZ, Position + 1, True);
     SB_PAGELEFT: SetScrollPos(Handle, SB_HORZ, Position - 10, True);
     SB_PAGERIGHT: SetScrollPos(Handle, SB_HORZ, Position + 10, True);
     SB_THUMBPOSITION, SB_THUMBTRACK:
       begin
         SI.cbSize := sizeof(SI);
         SI.fMask := SIF_ALL;
         GetScrollInfo(Handle, SB_HORZ, SI);
         SetScrollPos(Handle, SB_HORZ, SI.nTrackPos, True);
       end;
     SB_RIGHT: SetScrollPos(Handle, SB_HORZ, HMax, True);
     SB_LEFT: SetScrollPos(Handle, SB_HORZ, HMin, True);
   end;
 CaretPos := GetXYFromPosn(CaretP);
 Refresh;
end;


Работать то работает, да вот проблема с позицией курсора - не соответствует она действительности - т.е. не учитывается ширина букв, которая разная для каждой буквы. Понятно что нужно как бы самому рассчитывать ширину букв. Только как сделать - пока идей нет.



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

Форум: "Начинающим";
Текущий архив: 2015.09.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.043 c
15-1415741405
Юрий
2014-11-12 00:30
2015.09.10
С днем рождения ! 12 ноября 2014 среда


2-1395359190
alexdn
2014-03-21 03:46
2015.09.10
ComboBox


15-1417559265
Jeer
2014-12-03 01:27
2015.09.10
А вдруг?


15-1418592602
Юрий
2014-12-15 00:30
2015.09.10
С днем рождения ! 15 декабря 2014 понедельник


1-1330436331
Chrom
2012-02-28 17:38
2015.09.10
Отработка оператора Case





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский