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

Вниз

Во время показа hints мелькает фоном стандартная подсказка.   Найти похожие ветки 

 
Dr. Andrew   (2007-07-09 19:08) [0]

Доброго дня, Мастера!
Я использую свой собственный формат всплывающей подсказки hint объявленной в процедуре onFormCreate^
{* установить собственный формат подсказок *}
 Application.ShowHint := False;
 HintWindowClass := SGGraphicHint.TSGGraphicHintWindow;
 FHintWindow := HintWindowClass.Create(self);
 Application.ShowHint := True;

Проблема: во время показа hints мелькает фоном стандартная подсказка (желтое поле).
Вопрос: как можно отловить (hook или еще каким образом?) системную стандартную подсказку (вернее фоновое отображение ее Canvasа) и запретить ее появление одновременно с моим hint? Пожалуйста, приведите маленький пример. Всем спасибо!


 
Dr. Andrew   (2007-07-09 19:23) [1]

просто использование Application.ShowHint := False; не справляется. Что делать? Может что-то надо добавить в процедуру Paint своего компонента Hint, чтобы фоновый канвас не показывался на доли секунд перед выводом основного канваса?


 
Инс ©   (2007-07-09 19:32) [2]

Application.ShowHint := False;
HintWindowClass := SGGraphicHint.TSGGraphicHintWindow;
FHintWindow := HintWindowClass.Create(self);
FHintWindow.DoubleBuffered:=true;
Application.ShowHint := True;


Помогло?


 
Dr. Andrew   (2007-07-09 19:41) [3]

Спасибо, FHintWindow.DoubleBuffered:=true; не помогает, какие еще есть мысли? может hook применить, тогда как это сделать - можно пример?


 
Юрий Зотов ©   (2007-07-09 23:14) [4]

Показывайте код своего класса. Похоже, что-то там не так.


 
Dr. Andrew   (2007-07-09 23:36) [5]

{*********************************************************

Mit Hilfe des folgendes Codes lassen sich leicht beliebige
Hints erstellen. Dazu muss nur dir Prozedur "Paint" den
Wьnschen entsprechend angepasst werden.

With the following Code you can simply create custom hints.
You just have to change the procedur "Paint".

*********************************************************}

type
 TGraphicHintWindow = class(THintWindow)
   constructor Create(AOwner: TComponent); override;
 private
   FActivating: Boolean;
 public
   procedure ActivateHint(Rect: TRect; const AHint: string); override;
 protected
   procedure Paint; override;
 published
   property Caption;
 end;

 {...}

constructor TGraphicHintWindow.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);

 {
  Hier kцnnen beliebige Schrift Eigenschaften gesetzt
  werden.

  Here you can set custom Font Properties:
  }

 with Canvas.Font do
 begin
   Name := "Arial";
   Style := Style + [fsBold];
   Color := clBlack;
 end;
end;

procedure TGraphicHintWindow.Paint;
var
 R: TRect;
 bmp: TBitmap;
begin
 R := ClientRect;
 Inc(R.Left, 2);
 Inc(R.Top, 2);

 {*******************************************************
  Der folgende Code ist ein Beispiel wie man die Paint
  Prozedur nutzen kann um einen benutzerdefinierten Hint
  zu erzeugen.

  The folowing Code ist an example how to create a custom
  Hint Object. :
  }

 bmp := TBitmap.Create;
 bmp.LoadfromFile("D:\hint.bmp");

 with Canvas do
 begin
   Brush.Style := bsSolid;
   Brush.Color := clsilver;
   Pen.Color := clgray;
   Rectangle(0, 0, 18, R.Bottom + 1);
   Draw(2, (R.Bottom div 2) - (bmp.Height div 2), bmp);
 end;

 bmp.Free;
 //Beliebige HintFarbe
 //custom Hint Color
 Color := clWhite;

 Canvas.Brush.Style := bsClear;
 Canvas.TextOut(20, (R.Bottom div 2) - (Canvas.Textheight(Caption) div 2),
   Caption);
 {********************************************************}
end;

procedure TGraphicHintWindow.ActivateHint(Rect: TRect; const AHint: string);
begin
 FActivating := True;
 try
   Caption := AHint;
   //Hцhe des Hints setzen setzen
   //Set the "Height" Property of the Hint
   Inc(Rect.Bottom, 14);
   //Breite des Hints setzen
   //Set the "Width" Property of the Hint
   Rect.Right := Rect.Right + 20;
   UpdateBoundsRect(Rect);
   if Rect.Top + Height > Screen.DesktopHeight then
     Rect.Top := Screen.DesktopHeight - Height;
   if Rect.Left + Width > Screen.DesktopWidth then
     Rect.Left := Screen.DesktopWidth - Width;
   if Rect.Left < Screen.DesktopLeft then
     Rect.Left := Screen.DesktopLeft;
   if Rect.Bottom < Screen.DesktopTop then
     Rect.Bottom := Screen.DesktopTop;
   SetWindowPos(Handle, HWND_TOPMOST, Rect.Left, Rect.Top, Width, Height,
     SWP_SHOWWINDOW or SWP_NOACTIVATE);
   Invalidate;
 finally
   FActivating := False;
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 HintWindowClass := TGraphicHintWindow;
 Application.ShowHint := False;
 Application.ShowHint := True;
end;


ссылка на код: http://delphiworld.narod.ru/base/graphic_hint.html
при быстром перемещении мыши фоном бликом появляется стандартный желтый канвас или ширина санваса этого хинта сначала бликом растягивается до правого края экрана, а затем возвращается в нормально положение и все это за доли секунды, но они видны! спасибо за помощь!


 
Dr. Andrew   (2007-07-09 23:36) [6]

Мне кажется, что что-то не так в процедуре procedure TGraphicHintWindow.Paint, но что?


 
Юрий Зотов ©   (2007-07-10 00:58) [7]

Зачем перед отрисовкой битмапа создавать его и загружать из файла? Это же задержка отрисовки битмапа - и возможно, что причина в ней и есть.

В любом случае лучше создать и загрузить битмап один раз - притом заранее, в конструкторе. И уничтожить его тоже один раз, в деструкторе.


 
Dr. Andrew   (2007-07-10 01:28) [8]

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


 
Юрий Зотов ©   (2007-07-10 02:05) [9]

Не уверен, но одно подозрение есть...

В ActivateHint сначала вызывается SetWindowPos с SWP_SHOWWINDOW, а потом запрашивается перерисовка вызовом Invalidate. Похоже, что стандартная отрисовка происходит в результате вызова SetWindowPos, потом перемалывается куча сообщений и только после этого дело доходит до перерисовки. То есть, имеем то самое мелькание стандартного окна.

Если это так, то лучший выход - рисовать не в методе Paint, а в WndProc, непосредственно при обработке WM_PAINT. Можно попробовать и более простой вариант - в ActivateHint вызывать не Invalidate, а Repaint (чтобы форсировать перерисовку). Но первый способ лучше, поскольку он вообще никакой перерисовки не требует.


 
Dr. Andrew   (2007-07-10 02:35) [10]

Спасибо, но как это можно практически представить, опыта работы с WM_PAINT у меня нет. Можете помочь?


 
Dr. Andrew   (2007-07-10 02:39) [11]

вызов в ActivateHint Repaint вместо Invalidate не помогает. Увы!


 
MetalFan ©   (2007-07-10 08:53) [12]

не совсем понятно, зачем в примере перекрыт ActivateHint.
вот набросал небольшой пример, изменяется размер и выводится свой текст другим цветом в хинте.

 TMHintWindow = class( THintWindow )
 protected
   procedure Paint; override;
 public
   function CalcHintRect(MaxWidth: Integer; const AHint: string;
     AData: Pointer): TRect; override;
 end;
...
{ TMHintWindow }

function TMHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: string;
 AData: Pointer): TRect;
begin
 Result := inherited CalcHintRect( MaxWidth, AHint, AData );
 Inc( Result.Left, 50);
 Inc( Result.Bottom, 14);

end;

procedure TMHintWindow.Paint;
var
 lRect: TRect;
begin
 lRect := ClientRect;
 Canvas.Brush.Color := clRed;
 Canvas.Font.Color := clWhite;
 Canvas.TextRect( lRect, lRect.Left + 2, lRect.Top + 2, "TEST HINT" );
end;


 
MetalFan ©   (2007-07-10 08:59) [13]

+ еще если перекрыть NCPaint, то можно и рамочку нарисовать

 TMHintWindow = class( THintWindow )
...
   procedure NCPaint(DC: HDC); override;
...
procedure TMHintWindow.NCPaint(DC: HDC);
var
 R: TRect;
 lCanvas: TCanvas;
begin
 lCanvas := TCanvas.Create;
 try
   lCanvas.Handle := DC;
   lCanvas.Brush.Color := clBlack;
   lCanvas.Rectangle(0,0,Width, Height);
 finally
   lCanvas.Free;
 end;
end;


 
Инс ©   (2007-07-10 10:06) [14]


> В ActivateHint сначала вызывается SetWindowPos с SWP_SHOWWINDOW,
>  а потом запрашивается перерисовка вызовом Invalidate. Похоже,
>  что стандартная отрисовка происходит в результате вызова
> SetWindowPos, потом перемалывается куча сообщений и только
> после этого дело доходит до перерисовки. То есть, имеем
> то самое мелькание стандартного окна.


В ряд ли, все равно перерисовка осуществляется именно по приходу WM_ERASEBKGND и WM_PAINT, а обработчик у них только один, так что как как при SetWindowPos может происходить какая-то другая обработка? А Invalidate действительно стоит убрать.


> Если это так, то лучший выход - рисовать не в методе Paint,
>  а в WndProc, непосредственно при обработке WM_PAINT.

А это не имеет значения. Обработчик WM_PAINT и так вызывает Paint после вызова BeginPaint.

А вот из-за чего может быть проблема - так это из-за обработки WM_ERASEBKGND. Это сообщение имеет бОльший приоритет, чем WM_PAINT (поэтому последнее может быть обработано с задержкой), а в его обработчике по-умолчанию фон заливается определенной кистью (скорее всего - желтой). Такое поведение нужно задавить:

TGraphicHintWindow = class(THintWindow)
  constructor Create(AOwner: TComponent); override;
private
 procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  ...
end;

...

procedure TGraphicHintWindow.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
 Result:=1;  // Перекрываем старый обработчик пустышкой
end;


 
MetalFan ©   (2007-07-10 10:38) [15]

в примере тупо скопирована часть кода VCL.
и вообще, пример этот (из DWorld), имхо, не совсем удачный.


 
Инс ©   (2007-07-10 10:42) [16]

чуть подправлю, на коленке писал...

procedure TGraphicHintWindow.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
Message.Result:=1;  // Перекрываем старый обработчик пустышкой
end;


 
Rouse_ ©   (2007-07-10 11:38) [17]

Посмотри вот этот компонент: http://rouse.drkb.ru/components.php#fwhint
по его аналогу добавь к себе что у тебя забыто :)


 
Dr. Andrew   (2007-07-10 13:50) [18]

Инс Спасибо за диалог, но включение процедуры WMEraseBkgnd(var Message: TWMEraseBkgnd) не меняет, а даже ухудшает положение. Канвас подсказки становится черного цвета, а блики все равно есть. Использование CalcHintRect тоже не влияет на фоновую перерисовку. Есть еще мнений по данной проблеме?

Rouse_ Спасибо за совет, но поданной ссылке ничего не нашел, можно дать адрес точнее. Спасибо!


 
Rouse_ ©   (2007-07-10 14:03) [19]

Плохо искал :)
http://rouse.drkb.ru/files/fwhint.zip


 
Dr. Andrew   (2007-07-10 14:05) [20]

спасибо, не сразу обратил внимание, уже нашел, посмотрел, но там тоже нет решения пока.


 
Инс ©   (2007-07-10 14:32) [21]

Кинь-ка мне на мыло маленький демонстрационный примерчик данного хинт-виндоу.


 
Rouse_ ©   (2007-07-10 14:40) [22]


> но там тоже нет решения пока.

В смысле, тот пример тоже показывает фоном желтый цвет периодически?
А можно я скажу "не верю"? ;)


 
Dr. Andrew   (2007-07-10 15:11) [23]

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


 
Rouse_ ©   (2007-07-10 16:17) [24]

Так в моем примере размер канваса как раз кастомный, там вообще все кастомное :) Но бликов никогда небыло :)


 
Dr. Andrew   (2007-07-10 17:00) [25]

Я не имел ввиду пример fwhint.zip, я все время веду речь о приведенном мною выше коде собственного hint. И хочу понять, что вызывает долисекундные блики. А можно как-то перехватить создание стандартного канваса, например, с помощью hook? Я так понимаю, что вначале создается канвас стандартный желтого традиционного цвета, а затем идет перерисовка на мой канвас. Если можно отловить все это хуком, то можно небольшой пример как это сделать практически? Спасибо за помощь!


 
Rouse_ ©   (2007-07-10 17:45) [26]

Вот если ты всетаки посмотришь мой пример, то сможешь увидеть как сее действо происходит. См реализацию

 TFWHintWindow = class(THintWindow)
 private
   FHint: TFWHint;
   FBlend, FSRC: TBitmap;
 protected
   procedure CreateParams (var Params: TCreateParams); override;
   procedure Paint; override;
   procedure Erase(var Message: TMessage); message WM_ERASEBKGND;
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   procedure ActivateHint (HintRect: TRect; const AHint: string); Override;
 end;


 
MetalFan ©   (2007-07-10 23:18) [27]

а в чем необходимость перекрытия ActivateHint???


 
Dr. Andrew   (2007-07-10 23:30) [28]

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


 
Rouse_ ©   (2007-07-11 10:18) [29]

Я ничего не понимаю... Тебе дали код, ты его смотрел? Зачем задавать вопрос если решение у тебя уже есть? Касвас создается при создании окна, перед созданием окна перед регистрацией класса происходит вызов CreateParams... все перекрывается - все отрисовывается... бликов нет. Нафига тебе для такой простой задачи еще и хуки то понадобились?


 
Dr. Andrew   (2007-07-11 14:42) [30]

{jХорошою вайте поп порядку:
1. Введение процедуры - procedure CreateParams (var Params: TCreateParams); override; ничего не меняет, кроме тог что удаляется бордюр вокруг канваса подсказки, но это мелочь понятная.
2. Введение процедуры procedure Erase(var Message: TMessage); message WM_ERASEBKGND; с любым ее значением красит белый канвас в черный цвет с проступающим на нем цветным, например, текстом и дополнительно нарисовывает контуры канваса при каждом его перемещении, то есть канвас становится похожим на совокупность множества рамочек и подсказка становится нечитабельной.


 
Rouse_ ©   (2007-07-11 17:00) [31]

Paint забыл...


 
Dr. Andrew   (2007-07-11 17:10) [32]

так Paint у меня уже есть (смотри полный код выше), только несколько свой, что там модет быть не так?  А что происходит в процедуре Erase(var Message: TMessage), что она такое вытворяет? Спасибо за ответ.


 
MetalFan ©   (2007-07-11 18:47) [33]

Dr. Andrew ты
MetalFan ©   (10.07.07 08:53) [12]
видел? чем тебя не устраивает?


 
Dr. Andrew   (2007-07-11 18:50) [34]

просто я хочу разобраться в своем исходном коде. Может все же есть мнения у кого-то еще? Всем спасибо!


 
Rouse_ ©   (2007-07-11 21:43) [35]


> просто я хочу разобраться в своем исходном коде.

Самое простое разобраться сначала в чужом, чтобы потом понять что не так в своем :) Хотя конечно проще задать вопрос "что у меня не работает"... ;)



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

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

Наверх




Память: 0.55 MB
Время: 0.042 c
15-1188267803
ArtemESC
2007-08-28 06:23
2007.09.23
Ночью перечитал Евгения Онегина...


15-1187965934
AntiUser
2007-08-24 18:32
2007.09.23
Курьёзный случай произошел в США


3-1179599806
ARTEM779
2007-05-19 22:36
2007.09.23
проблема с дочерными окнами


5-1158241346
Slava80
2006-09-14 17:42
2007.09.23
TrackBar с присоединенным полем Edit


15-1188223902
@!!ex
2007-08-27 18:11
2007.09.23
Как искать утечки памяти?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский