Форум: "Основная";
Текущий архив: 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