Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  07:57[Войти] | [Зарегистрироваться]
Ответ на вопрос № 74005

10-11-2009 05:11
Доброго всем дня.
Создаю компонент, наследник от TCustomTransparentControl. Необходимость следующая: в зависимости от InterceptMouse он будет прозрачен или реагировать на мышу. То чтобы он был прозрачен в самом TCustomTransparentControl поддерживается. Но вот реакции, когда он непрозрачен от него добиться не могу.


TTransparentControl = class(TCustomTransparentControl)
  private
    FOnPaint: TNotifyEvent;
  protected
    procedure Paint; override;
  public
    property InterceptMouse;
    constructor Create(AOwner: TComponent); override;
  published
    property OnClick;
    property OnMouseMove;
    property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  end;


implementation


{** TTransparentControl **}

constructor TTransparentControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle + [csOpaque];
  Brush.Style := bsClear;
  with Canvas do
  begin
    Pen.Style := psDash;
    Pen.Color := clBlack;
    Brush.Style := bsClear;
  end;
end;


procedure TTransparentControl.Paint;
begin
  inherited;
  if csDesigning in ComponentState then
    Canvas.Rectangle(0, 0, Width, Height);
  if Assigned(FOnPaint) then FOnPaint(Self);
end;


то есть, когда он прозрачен контролы под ним реагируют на мышь. Когда ставлю программно ему флаг непрозрачности, контролы под ним перестают реагировать, но и он никаких признаков жизни не подаёт.
Все действия по реакции на мышь описаны в родителе TWinControl, поэтому он как наследник вроде должен уметь их обрабатывать, но что-то никак (((.

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

11-11-2009 04:15
В классе TCustomTransparentControl стоит неверная обработка сообщения
Я проверял на D2010, там все исправлено.

11-11-2009 02:48 | Сообщение от автора вопроса
Кстати забыла сказать, что создала свой прозрачный контрол не от TCustomTransparentControl, а непосредственно от TCustomControl, продублировав большую часть кода от TCustomTransparentControl, с указаным измененим в обработчике сообщения WM_NCHITTEST, плюс небольшую свою функциональность. То есть получила гибрид


type

  TTransparentControl = class(TCustomControl)
  private
    FInterceptMouse: Boolean;
    FOnPaint: TNotifyEvent;
  protected
    procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure InvalidateControlsUnderneath;
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure Invalidate; override;
    property InterceptMouse: Boolean read FInterceptMouse write FInterceptMouse default False;
  published
    property OnClick;
    property OnMouseMove;
    property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  end;


implementation


{** TTransperentControl **}

//------------------------------------------------------------------------------
constructor TTransparentControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle + [csReplicatable, csOpaque];
  Brush.Style := bsClear;
  with Canvas do
  begin
    Pen.Style := psDash;
    Pen.Color := clBlack;
    Brush.Style := bsClear;
  end;
end;
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
procedure TTransparentControl.Paint;
begin
  inherited;
  if csDesigning in ComponentState then
    Canvas.Rectangle(0, 0, Width, Height);

  if Assigned(FOnPaint) then FOnPaint(Self);
end;
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
procedure TTransparentControl.InvalidateControlsUnderneath;
var
  I: Integer;
  Invalidating: Boolean;
  Control: TControl;

  procedure DoInvalidate(AControl: TControl);
  var
    I: Integer;
    Control: TControl;
  begin
    if AControl is TWinControl then
    begin
      if TWinControl(AControl).HandleAllocated then
        with TWinControl(AControl) do
        begin
          RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_FRAME);
          InvalidateRect(Handle, nil, True);
        end;
      if (csAcceptsControls in AControl.ControlStyle) then
        for I := 0 to TWinControl(AControl).ControlCount - 1 do
        begin
          Control := TWinControl(AControl).Controls[I];
          DoInvalidate(Control);
        end;
    end else
      AControl.Invalidate;
  end;

begin
  Invalidating := False;
  if HandleAllocated then
  begin
    for I := Parent.ControlCount - 1 downto 0 do
    begin
      Control := Parent.Controls[I];
      if Invalidating then
        DoInvalidate(Control)
      else if Control = Self then
        Invalidating := True;
    end;
    InvalidateRect(Parent.Handle, nil, True);
  end;
end;
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
procedure TTransparentControl.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT;
end;
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
procedure TTransparentControl.WMNCHitTest(var Message: TWMNCHitTest);
begin
  if not FInterceptMouse then
    Message.Result := HTTRANSPARENT
  else
    inherited;
end;
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
procedure TTransparentControl.Invalidate;
begin
  InvalidateControlsUnderneath;
  inherited Invalidate;
end;
//------------------------------------------------------------------------------



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

11-11-2009 02:41 | Сообщение от автора вопроса
Проблема разрешилась )))
В классе TCustomTransparentControl стоит неверная обработка сообщения


procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
...
procedure TCustomTransparentControl.WMNCHitTest(var Message: TWMNCHitTest);
begin
  if not FInterceptMouse then
    Message.Result := HTTRANSPARENT;
end;


Её нужно скорректировать, и у себя добавить свой обработчик, но уже


procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
...
procedure TTransparentControl.WMNCHitTest(var Message: TWMNCHitTest);
begin
  if not FInterceptMouse then
    Message.Result := HTTRANSPARENT
  else
    inherited;
end;



11-11-2009 02:11 | Сообщение от автора вопроса
По такому коду не совсем понят сигнал от панельки идёт или от формы. Вы измените


procedure TForm1.FormClick(Sender: TObject);
begin
  ShowMessage(Sender.ClassName);
end;


10-11-2009 10:46
Хм, похоже вы правы. Описаное мной действие этот флаг оказывает только на слоистые окна. И кстати я сейчас проверил ваш код - все отлично работает:

procedure TForm1.FormClick(Sender: TObject);
begin
  Beep;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  tc.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  tc := TTransparentControl.Create(Self);
  tc.Left:=5;
  tc.Top:=5;
  tc.Width:=50;
  tc.Height:=30;
  tc.Parent:=Self;
  tc.OnClick:=formclick;
//  tc.Visible:=True;
  tc.InterceptMouse := True;
end;


10-11-2009 08:19 | Сообщение от автора вопроса
Я сбросила этот флаг и стало понятно зачем он был установлен. При устновленном флаге контролы, лежащие под такой панелькой не только реагируют на мышь, но и видны, а когда снять этот флаг, то они пропадают. А вот сбрасывание флага не помогло, всё равно панелька не реагирует на мышь (((
Кстати оговорюсь, что просвечивание контролов под панелькой мне как раз актуально.

10-11-2009 08:08
TCategoryPanel и сопутствующие ему класы появились вроде только в D2009.
Вобщем суть такова, что WS_EX_TRANSPARENT полностью отключает у окна реакцию на мишь. Зачем это было реализовывать если есть InterceptMouse я не знаю. Но вы легко можете сбросить этот флаг если перекроете в своем наследнике CreateParams:

procedure TCategoryPanelSurface.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle and not WS_EX_TRANSPARENT;
end;


10-11-2009 07:35 | Сообщение от автора вопроса
Я что-то в ExtCtrls не могу найти TCategoryPanelSurface (Делфи 2007) (((
А на счёт TCustomTransparentControl.CreateParams у меня тоже под подозрением, но я не совсем понимаю, как его сбросить и в какой момент. Мне казалось, что этот метод вызывается один раз при создании, а я программно меняю галку, то есть уже после создания. Хотя, скорее всего я ошибаюсь по части того, когда он вызывается. Подскажите, плз.

10-11-2009 07:15
Гляньте метод TCustomTransparentControl.CreateParams, там устанавливается флаг WS_EX_TRANSPARENT. Я думаю, вам нужно его сбросить, по крайней мере ExtCtrls.TCategoryPanelSurface именно так и делает.

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Кто съел Красную шапочку?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

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

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования