{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is: JvDesktopAlertForm.PAS, released on 2004-03-24. The Initial Developer of the Original Code is Peter Thornqvist Portions created by Peter Thornqvist are Copyright (C) 2004 Peter Thornqvist. All Rights Reserved. Contributor(s): Hans-Eric Grönlund (stack logic) Olivier Sannier (animation styles logic) You may retrieve the latest version of this file at the Project JEDI's JVCL home page, located at http://jvcl.sourceforge.net Known Issues: * This form is used by the TJvDesktopAlert component -----------------------------------------------------------------------------} // $Id: JvDesktopAlertForm.pas 11057 2006-11-29 14:32:05Z marquardt $ unit JvDesktopAlertForm; {$I jvcl.inc} interface uses {$IFDEF UNITVERSIONING} JclUnitVersioning, {$ENDIF UNITVERSIONING} Windows, Messages, Classes, Graphics, Controls, Forms, StdCtrls, ExtCtrls, ImgList, ActnList, JvButton, JvLabel, JvComponent, JvConsts, JvExForms; const cDefaultAlertFormWidth = 329; cDefaultAlertFormHeight = 76; JVDESKTOPALERT_AUTOFREE = WM_USER + 1001; type TJvDesktopAlertButtonType = (abtArrowLeft, abtArrowRight, abtClose, abtMaximize, abtMinimize, abtDropDown, abtDropDownChevron, abtRestore, abtImage); TJvDesktopAlertButton = class(TJvCustomGraphicButton) private FChangeLink: TChangeLink; FImages: TCustomImageList; FImageIndex: TImageIndex; FToolType: TJvDesktopAlertButtonType; FInternalClick: TNotifyEvent; procedure SetImages(const Value: TCustomImageList); procedure SetImageIndex(const Value: TImageIndex); procedure DoImagesChange(Sender: TObject); procedure SetToolType(const Value: TJvDesktopAlertButtonType); protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure Paint; override; procedure MouseEnter(Control: TControl); override; procedure MouseLeave(Control: TControl); override; public property InternalClick: TNotifyEvent read FInternalClick write FInternalClick; constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property ToolType: TJvDesktopAlertButtonType read FToolType write SetToolType; property DropDownMenu; property Images: TCustomImageList read FImages write SetImages; property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; property Width default 21; property Height default 21; property OnClick; end; TJvFormDesktopAlert = class(TJvExCustomForm) private FOnMouseLeave: TNotifyEvent; FOnMouseEnter: TNotifyEvent; FOnUserMove: TNotifyEvent; acClose: TAction; MouseTimer: TTimer; FEndInterval:Cardinal; FMouseInControl: Boolean; FCloseable: Boolean; FMoveable: Boolean; FMoveAnywhere: Boolean; FAllowFocus: Boolean; FClickableMessage: Boolean; FCaptionColorTo: TColor; FWindowColorTo: TColor; FWindowColorFrom: TColor; FCaptionColorFrom: TColor; FFrameColor: TColor; FOnShown: TNotifyEvent; FOnShowing: TNotifyEvent; {$IFDEF VCL} procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST; procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE; procedure WMMouseActivate(var Message: TWMMouseActivate); message WM_MOUSEACTIVATE; procedure WMMove(var Msg: TWMMove); message WM_MOVE; {$ENDIF VCL} procedure JvDeskTopAlertAutoFree(var Msg: TMessage); message JVDESKTOPALERT_AUTOFREE; procedure DoMouseTimer(Sender: TObject); procedure FormPaint(Sender: TObject); function GetVisible: Boolean; protected procedure DoShow; override; procedure DoClose(var Action: TCloseAction); override; procedure MouseEnter(AControl: TControl); override; procedure MouseLeave(AControl: TControl); override; procedure DoDropDownClose(Sender: TObject); procedure DoDropDownMenu(Sender: TObject; MousePos: TPoint; var Handled: Boolean); public imIcon: TImage; lblText: TJvLabel; lblHeader: TLabel; tbDropDown: TJvDesktopAlertButton; tbClose: TJvDesktopAlertButton; public constructor Create(AOwner: TComponent); override; procedure acCloseExecute(Sender: TObject); procedure SetNewTop(const Value: Integer); procedure SetNewLeft(const Value: Integer); procedure SetNewOrigin(ALeft, ATop: Integer); procedure DoButtonClick(Sender: TObject); procedure ShowNoActivate; property Moveable: Boolean read FMoveable write FMoveable; property MoveAnywhere: Boolean read FMoveAnywhere write FMoveAnywhere; property Closeable: Boolean read FCloseable write FCloseable; property ClickableMessage: Boolean read FClickableMessage write FClickableMessage; property MouseInControl: Boolean read FMouseInControl; property WindowColorFrom: TColor read FWindowColorFrom write FWindowColorFrom; property WindowColorTo: TColor read FWindowColorTo write FWindowColorTo; property CaptionColorFrom: TColor read FCaptionColorFrom write FCaptionColorFrom; property CaptionColorTo: TColor read FCaptionColorTo write FCaptionColorTo; property FrameColor: TColor read FFrameColor write FFrameColor; property AllowFocus: Boolean read FAllowFocus write FAllowFocus; property Showing read GetVisible; property Visible read GetVisible; property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; property OnUserMove: TNotifyEvent read FOnUserMove write FOnUserMove; property ParentFont; property PopupMenu; property OnClose; property OnShowing: TNotifyEvent read FOnShowing write FOnShowing; property OnShow; property OnShown: TNotifyEvent read FOnShown write FOnShown; end; {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvDesktopAlertForm.pas $'; Revision: '$Revision: 11057 $'; Date: '$Date: 2006-11-29 15:32:05 +0100 (mer., 29 nov. 2006) $'; LogPath: 'JVCL\run' ); {$ENDIF UNITVERSIONING} implementation uses Menus, SysUtils, JvJVCLUtils, JvDesktopAlert, JvResources; {.$R *.dfm} // not needed const cAlphaIncrement = 5; cCaptionHeight = 8; JvDefaultCaptionDotColor = TColor($00F8FCF8); JvDefaultCaptionDotShadowColor = TColor($00B8BCB8); JvDefaultTrackBorderColor = TColor($00663300); JvDefaultHotTrackColor = TColor($00CC9999); JvDefaultTrackColor = TColor($00D6BEB5); procedure DrawDesktopAlertCaption(Canvas: TCanvas; ARect: TRect; ColorFrom, ColorTo: TColor; DrawDots: Boolean); var I: Integer; R: TRect; begin GradientFillRect(Canvas, ARect, ColorFrom, ColorTo, fdTopToBottom, cCaptionHeight); R := ARect; Inc(R.Left, (R.Right - R.Left) div 2 - 20); Inc(R.Top, 3); R.Right := R.Left + 2; R.Bottom := R.Top + 2; if DrawDots then for I := 0 to 9 do // draw the dots begin Canvas.Brush.Color := clGray; Canvas.FillRect(R); OffsetRect(R, 1, 1); Canvas.Brush.Color := JvDefaultCaptionDotColor; Canvas.FillRect(R); Canvas.Brush.Color := JvDefaultCaptionDotShadowColor; Canvas.FillRect(Rect(R.Left, R.Top, R.Left + 1, R.Top + 1)); OffsetRect(R, 3, -1); end; end; procedure DrawDesktopAlertWindow(Canvas: TCanvas; WindowRect: TRect; FrameColor: TColor; WindowColorFrom, WindowColorTo, CaptionColorFrom, CaptionColorTo: TColor; DrawDots: Boolean); var CaptionRect: TRect; ATop: Integer; AColors: Byte; begin CaptionRect := WindowRect; CaptionRect.Bottom := CaptionRect.Top + cCaptionHeight; DrawDesktopAlertCaption(Canvas, CaptionRect, CaptionColorFrom, CaptionColorTo, DrawDots); ATop := WindowRect.Top; WindowRect.Top := CaptionRect.Bottom + 1; Dec(WindowRect.Bottom); if WindowRect.Bottom - WindowRect.Top < 255 then AColors := WindowRect.Bottom - WindowRect.Top else AColors := 32; GradientFillRect(Canvas, WindowRect, WindowColorFrom, WindowColorTo, fdTopToBottom, AColors); WindowRect.Top := ATop; Inc(WindowRect.Bottom); Canvas.Brush.Color := clGray; {$IFDEF VCL} Canvas.FrameRect(WindowRect); {$ENDIF VCL} {$IFDEF VisualCLX} FrameRect(Canvas, WindowRect); {$ENDIF VisualCLX} end; //=== { TJvFormDesktopAlert } ================================================ constructor TJvFormDesktopAlert.Create(AOwner: TComponent); begin inherited CreateNew(AOwner, 1); {$IFDEF VCL} Font.Assign(Screen.IconFont); {$ENDIF VCL} {$IFDEF VisualCLX} Font.Assign(Application.Font); {$ENDIF VisualCLX} MouseTimer := TTimer.Create(Self); MouseTimer.Enabled := False; MouseTimer.Interval := 200; MouseTimer.OnTimer := DoMouseTimer; MouseTimer.Enabled := True; BorderStyle := fbsNone; BorderIcons := []; Scaled := False; Height := cDefaultAlertFormHeight; Width := cDefaultAlertFormWidth; OnPaint := FormPaint; imIcon := TImage.Create(Self); imIcon.Parent := Self; imIcon.SetBounds(8, 11, 32, 32); imIcon.AutoSize := True; imIcon.Transparent := True; lblHeader := TLabel.Create(Self); lblHeader.Parent := Self; lblHeader.SetBounds(48, 11, 71, 13); lblHeader.Font.Style := [fsBold]; lblHeader.Transparent := True; lblText := TJvLabel.Create(Self); lblText.Parent := Self; lblText.SetBounds(56, 24, 67, 13); lblText.Transparent := True; lblText.WordWrap := True; lblText.Anchors := [akLeft..akBottom]; acClose := TAction.Create(Self); acClose.Caption := RsClose; acClose.ShortCut := ShortCut(VK_F4, [ssAlt]); // 32883 acClose.OnExecute := acCloseExecute; tbClose := TJvDesktopAlertButton.Create(Self); tbClose.ToolType := abtClose; tbClose.Parent := Self; tbClose.SetBounds(Width - 17, cCaptionHeight + 2, 15, 15); tbClose.Anchors := [akRight, akTop]; tbDropDown := TJvDesktopAlertButton.Create(Self); tbDropDown.ToolType := abtDropDown; tbDropDown.Parent := Self; tbDropDown.BoundsRect := tbClose.BoundsRect; tbDropDown.Left := tbDropDown.Left - 16; tbDropDown.Anchors := [akRight, akTop]; tbDropDown.OnDropDownMenu := DoDropDownMenu; tbDropDown.OnDropDownClose := DoDropDownClose; end; procedure TJvFormDesktopAlert.FormPaint(Sender: TObject); begin DrawDesktopAlertWindow(Canvas, ClientRect, FrameColor, WindowColorFrom, WindowColorTo, CaptionColorFrom, CaptionColorTo, Moveable or MoveAnywhere); end; {$IFDEF VCL} procedure TJvFormDesktopAlert.WMNCHitTest(var Msg: TWMNCHitTest); var P: TPoint; begin with Msg do P := ScreenToClient(Point(XPos, YPos)); if ((P.Y <= cCaptionHeight) and Moveable) or (MoveAnywhere and (ControlAtPos(P, False) = nil)) then begin TJvDesktopAlert(Owner).StyleHandler.AbortAnimation; Msg.Result := HTCAPTION; end else inherited; end; procedure TJvFormDesktopAlert.WMActivate(var Message: TWMActivate); begin if (Message.Active = WA_INACTIVE) or AllowFocus then inherited else Message.Result := 1; end; {$ENDIF VCL} procedure TJvFormDesktopAlert.acCloseExecute(Sender: TObject); begin if Closeable then Close; end; procedure TJvFormDesktopAlert.MouseEnter(AControl: TControl); begin inherited MouseEnter(AControl); FMouseInControl := True; // SetFocus; TJvDesktopAlert(Owner).StyleHandler.AbortAnimation; if Assigned(FOnMouseEnter) then FOnMouseEnter(Self); end; procedure TJvFormDesktopAlert.MouseLeave(AControl: TControl); var P: TPoint; begin inherited MouseLeave(AControl); // make sure the mouse actually left the outer boundaries GetCursorPos(P); if MouseInControl and not PtInRect(BoundsRect, P) then begin if Assigned(FOnMouseLeave) then FOnMouseLeave(Self); if not TJvDesktopAlert(Owner).StyleHandler.Active and (TJvDesktopAlert(Owner).StyleHandler.DisplayDuration > 0) then TJvDesktopAlert(Owner).StyleHandler.DoEndAnimation; FMouseInControl := False; end; end; procedure TJvFormDesktopAlert.DoShow; begin if Assigned(OnShowing) then OnShowing(Self); inherited DoShow; TJvDesktopAlert(Owner).StyleHandler.AbortAnimation; lblText.HotTrackFont.Style := [fsUnderLine]; lblText.HotTrackFont.Color := clNavy; if ClickableMessage then begin lblText.HotTrack := True; lblText.Cursor := crHandPoint; end else begin lblText.HotTrack := False; lblText.Cursor := crDefault; end; if tbDropDown.DropDownMenu = nil then tbDropDown.Visible := False; // if the form is not closeable, then do not show the button if not Closeable then begin tbClose.Visible := False; tbDropDown.Left := tbClose.Left; end; imIcon.Top := 13; lblHeader.Top := imIcon.Top; lblHeader.Left := imIcon.Left + imIcon.Width + 5; lblText.Left := lblHeader.Left + 8; lblText.Width := tbDropDown.Left - lblText.Left; lblText.Top := lblHeader.Top + lblHeader.Height; TJvDesktopAlert(Owner).StyleHandler.DoStartAnimation; MouseTimer.Enabled := True; if Assigned(OnShown) then OnShown(Self); end; {$IFDEF VCL} procedure TJvFormDesktopAlert.WMMove(var Msg: TWMMove); begin inherited; if Showing and Assigned(FOnUserMove) then FOnUserMove(Self); end; {$ENDIF VCL} procedure TJvFormDesktopAlert.SetNewTop(const Value: Integer); begin SetNewOrigin(Left, Value); end; procedure TJvFormDesktopAlert.SetNewLeft(const Value: Integer); begin SetNewOrigin(Value, Top); end; procedure TJvFormDesktopAlert.SetNewOrigin(ALeft, ATop: Integer); var MoveEvent: TNotifyEvent; begin if ((Top <> ATop) or (Left <> ALeft)) and not MouseInControl then begin MoveEvent := FOnUserMove; FOnUserMove := nil; Left := ALeft; Top := ATop; FOnUserMove := MoveEvent; end; end; procedure TJvFormDesktopAlert.DoMouseTimer(Sender: TObject); var P: TPoint; function IsInForm(P: TPoint): Boolean; var W: TControl; begin W := ControlAtPos(P, True, True); Result := (W = Self) or (FindVCLWindow(P) = Self) or ((W <> nil) and (GetParentForm(W) = Self)); end; begin // this is here to ensure that MouseInControl is correctly set even // if we never got a CM_MouseLeave (that happens a lot) MouseTimer.Enabled := False; GetCursorPos(P); FMouseInControl := PtInRect(BoundsRect, P); // and IsInForm(P); MouseTimer.Enabled := True; if not TJvDesktopAlert(Owner).StyleHandler.Active and not MouseInControl and (TJvDesktopAlert(Owner).StyleHandler.DisplayDuration > 0) then TJvDesktopAlert(Owner).StyleHandler.DoEndAnimation; end; procedure TJvFormDesktopAlert.DoClose(var Action: TCloseAction); begin MouseTimer.Enabled := False; inherited DoClose(Action); if Action = caHide then ShowWindow(Handle, SW_HIDE); end; //=== { TJvDesktopAlertButton } ============================================== constructor TJvDesktopAlertButton.Create(AOwner: TComponent); begin inherited Create(AOwner); FChangeLink := TChangeLink.Create; FChangeLink.OnChange := DoImagesChange; Width := 21; Height := 21; end; destructor TJvDesktopAlertButton.Destroy; begin FChangeLink.Free; inherited Destroy; end; procedure TJvDesktopAlertButton.DoImagesChange(Sender: TObject); begin Invalidate; end; procedure TJvDesktopAlertButton.MouseEnter(Control: TControl); begin inherited; Invalidate; end; procedure TJvDesktopAlertButton.MouseLeave(Control: TControl); begin inherited; Invalidate; end; procedure TJvDesktopAlertButton.Notification(AComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent, Operation); if Operation = opRemove then if AComponent = Images then Images := nil; end; procedure TJvDesktopAlertButton.Paint; const cMarlett = 'Marlett'; var Rect: TRect; begin with Canvas do begin Rect := ClientRect; Brush.Style := bsClear; if bsMouseInside in MouseStates then begin Pen.Color := JvDefaultTrackBorderColor; Rectangle(Rect); InflateRect(Rect, -1, -1); if bsMouseDown in MouseStates then Brush.Color := JvDefaultHotTrackColor else Brush.Color := JvDefaultTrackColor; FillRect(Rect); end; case ToolType of abtArrowLeft: begin Canvas.Font.Name := cMarlett; Canvas.Font.Style := []; Canvas.Font.Size := 10; DrawText(Canvas.Handle, '3', 1, Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER); end; abtArrowRight: begin Canvas.Font.Name := cMarlett; Canvas.Font.Style := []; Canvas.Font.Size := 10; DrawText(Canvas.Handle, '4', 1, Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER); end; abtClose: begin Canvas.Font.Name := cMarlett; Canvas.Font.Size := 7; Canvas.Font.Style := []; DrawText(Canvas.Handle, 'r', 1, Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER); end; abtMaximize: begin Canvas.Font.Name := cMarlett; Canvas.Font.Style := []; DrawText(Canvas.Handle, '2', 1, Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER); end; abtMinimize: begin Canvas.Font.Name := cMarlett; Canvas.Font.Style := []; DrawText(Canvas.Handle, '1', 1, Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER); end; abtDropDown: begin Canvas.Font.Name := cMarlett; Canvas.Font.Size := 10; Canvas.Font.Style := []; DrawText(Canvas.Handle, 'u', 1, Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER); end; abtDropDownChevron: begin // area should be 7x12 InflateRect(Rect, -((Rect.Right - Rect.Left) - 7) div 2, -((Rect.Bottom - Rect.Top) - 12) div 2); Canvas.Pen.Color := clWindowText; Canvas.MoveTo(Rect.Left, Rect.Top); Canvas.LineTo(Rect.Left + 2, Rect.Top); Canvas.MoveTo(Rect.Left + 3, Rect.Top); Canvas.LineTo(Rect.Left + 5, Rect.Top); OffsetRect(Rect, 1, 1); Canvas.MoveTo(Rect.Left, Rect.Top); Canvas.LineTo(Rect.Left + 2, Rect.Top); Canvas.MoveTo(Rect.Left + 3, Rect.Top); Canvas.LineTo(Rect.Left + 5, Rect.Top); OffsetRect(Rect, 1, 1); Canvas.MoveTo(Rect.Left, Rect.Top); Canvas.LineTo(Rect.Left + 2, Rect.Top); Canvas.MoveTo(Rect.Left + 3, Rect.Top); Canvas.LineTo(Rect.Left + 5, Rect.Top); OffsetRect(Rect, -1, 1); Canvas.MoveTo(Rect.Left, Rect.Top); Canvas.LineTo(Rect.Left + 2, Rect.Top); Canvas.MoveTo(Rect.Left + 3, Rect.Top); Canvas.LineTo(Rect.Left + 5, Rect.Top); OffsetRect(Rect, -1, 1); Canvas.MoveTo(Rect.Left, Rect.Top); Canvas.LineTo(Rect.Left + 2, Rect.Top); Canvas.MoveTo(Rect.Left + 3, Rect.Top); Canvas.LineTo(Rect.Left + 5, Rect.Top); OffsetRect(Rect, 1, 4); Canvas.MoveTo(Rect.Left, Rect.Top); Canvas.LineTo(Rect.Left + 5, Rect.Top); OffsetRect(Rect, 1, 1); Canvas.MoveTo(Rect.Left, Rect.Top); Canvas.LineTo(Rect.Left + 3, Rect.Top); OffsetRect(Rect, 1, 1); Canvas.MoveTo(Rect.Left, Rect.Top); Canvas.LineTo(Rect.Left + 1, Rect.Top); end; abtRestore: begin Canvas.Font.Name := cMarlett; Canvas.Font.Style := []; DrawText(Canvas.Handle, '3', 1, Rect, DT_SINGLELINE or DT_CENTER or DT_VCENTER); end; abtImage: begin if (Images = nil) or (ImageIndex < 0) or (ImageIndex >= Images.Count) then Exit; Images.Draw(Canvas, (Width - Images.Width) div 2 + Ord(bsMouseDown in MouseStates), (Height - Images.Height) div 2 + Ord(bsMouseDown in MouseStates), ImageIndex, {$IFDEF COMPILER6_UP} {$IFDEF VCL} dsTransparent, {$ENDIF VCL} itImage, {$ENDIF COMPILER6_UP} Enabled); end; end; end; end; procedure TJvDesktopAlertButton.SetImageIndex(const Value: TImageIndex); begin if FImageIndex <> Value then begin FImageIndex := Value; Invalidate; end; end; procedure TJvDesktopAlertButton.SetImages(const Value: TCustomImageList); begin if FImages <> Value then begin if FImages <> nil then FImages.UnRegisterChanges(FChangeLink); FImages := Value; if FImages <> nil then begin FImages.FreeNotification(Self); FImages.RegisterChanges(FChangeLink); end; Invalidate; end; end; procedure TJvDesktopAlertButton.SetToolType(const Value: TJvDesktopAlertButtonType); begin if FToolType <> Value then begin FToolType := Value; Invalidate; end; end; procedure TJvFormDesktopAlert.JvDeskTopAlertAutoFree(var Msg: TMessage); begin // WParam is us, LParam is the TJvDesktopAlert if Msg.WParam = WPARAM(Self) then begin Release; TObject(Msg.LParam).Free; end; end; procedure TJvFormDesktopAlert.DoButtonClick(Sender: TObject); var FEndInterval: Cardinal; begin if Sender is TJvDesktopAlertButton then begin FEndInterval := TJvDesktopAlert(Owner).StyleHandler.EndInterval; try // stop the animation while the OnClick handler executes: // we don't want the form to disappear before we return TJvDesktopAlert(Owner).StyleHandler.EndInterval := 0; if Assigned(TJvDesktopAlertButton(Sender).InternalClick) then TJvDesktopAlertButton(Sender).InternalClick(Sender); finally TJvDesktopAlert(Owner).StyleHandler.EndInterval := FEndInterval; if not MouseInControl then TJvDesktopAlert(Owner).StyleHandler.DoEndAnimation; end; end; end; procedure TJvFormDesktopAlert.DoDropDownClose(Sender: TObject); begin // restore previous EndInterval value if FEndInterval <> 0 then TJvDesktopAlert(Owner).StyleHandler.EndInterval := FEndInterval; FEndInterval := 0; if not MouseInControl then TJvDesktopAlert(Owner).StyleHandler.DoEndAnimation; end; procedure TJvFormDesktopAlert.DoDropDownMenu(Sender: TObject; MousePos: TPoint; var Handled: Boolean); begin // suspend the form while the menu is visible FEndInterval := TJvDesktopAlert(Owner).StyleHandler.EndInterval; TJvDesktopAlert(Owner).StyleHandler.EndInterval := 0; end; procedure TJvFormDesktopAlert.WMMouseActivate(var Message: TWMMouseActivate); begin if AllowFocus then inherited else Message.Result := MA_NOACTIVATE; end; procedure TJvFormDesktopAlert.ShowNoActivate; begin Include(FFormState, fsShowing); // Windows.SetParent(Handle, 0); //-- The above was introduced to partially solve the issue of the visible //-- TJvFormDesktopAlert(s) dropping behind another App when this App is //-- defocused. //-- Unfortunately, this re-introduces the bug of momentarily taking the focus //-- away from the active form within this App, when it has the focus. //-- A further side-effect is to set Application.Active := True SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_NOREDRAW or SWP_NOSENDCHANGING); DoShow; Exclude(FFormState, fsShowing); Include(FFormState, fsVisible); end; function TJvFormDesktopAlert.GetVisible: Boolean; begin Result := IsWindowVisible(Handle); end; initialization {$IFDEF UNITVERSIONING} RegisterUnitVersion(HInstance, UnitVersioning); {$ENDIF UNITVERSIONING} RegisterClasses([TLabel, TImage, TAction, TJvDesktopAlertButton, TJvLabel]); {$IFDEF UNITVERSIONING} finalization UnregisterUnitVersion(HInstance); {$ENDIF UNITVERSIONING} end.