以前写的, <br>unit uRSIPopupForm;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br> Dialogs, StdCtrls<br>{$IFDEF DEBUG}<br> , dbugintf<br>{$ENDIF DEBUG}<br> ,Buttons, ExtCtrls, ActnList, Contnrs ;<br><br>const<br> gcs_ActionParam = 'action';<br> gcc_ActionCommand = #3;<br><br><br>type<br> TRSIPopupForm = class(TForm)<br> pan_base: TPanel;<br> Pan_Title: TPanel;<br> btn_Toggle: TSpeedButton;<br> btn_Exit: TSpeedButton;<br> Label1: TLabel;<br> procedure FormCreate(Sender: TObject);<br> procedure FormDestroy(Sender: TObject);<br> procedure Pan_TitleResize(Sender: TObject);<br> procedure btn_ExitClick(Sender: TObject);<br> procedure Pan_TitleMouseDown(Sender: TObject; Button: TMouseButton;<br> Shift: TShiftState; X, Y: Integer);<br> procedure FormShow(Sender: TObject);<br> Private<br> //Capture<br> FFormHandle : THandle;<br> FCapturing : boolean;<br> FNCACTIVATE : boolean;<br> FShowing : boolean ;<br> FTimer : TTimer;<br> FRect : TRECT;<br> FLastHitTestTime : integer;<br> FHandlerList : TObjectList;<br> function InWindows:boolean;<br> function InWinControl:boolean;<br> procedure InitAllControlMessageHandler(pvo_ParentControl : TControl);<br> procedure InitControlMessageHandler(pvo_HandledControl : TControl);<br> procedure FreeControlMessageHandler;<br> procedure ResetNCActivate;<br> procedure TimerOnTimer(Sender: TObject);<br> procedure SetCapturing(Value : boolean) ;<br> Property Capturing : boolean read FCapturing write SetCapturing;<br> private<br> FToggle : boolean ;<br> FPopup: boolean;<br> Protected<br> procedure WndProc(var Message: TMessage); override;<br> procedure CreateParams(var Params : TCreateParams); override;<br> procedure ShowFormByName(FormName : string);<br> public<br> { Public declarations }<br> published<br> property Popup : boolean read FPopup write FPopup;<br> property Toggle : boolean read FToggle write FToggle;<br> end;<br><br> TRSIPopupFormClass = Class of TRSIPopupForm;<br><br> TControlMessageHandler = class(TObject)<br> private<br> FParentForm : TRSIPopupForm;<br> FControl : TControl;<br> FOldWindowProc : procedure(var Message: TMessage) of Object;<br> procedure NewWindowProc(var Message: TMessage);<br> end;<br><br><br>var<br> RSIPopupForm: TRSIPopupForm;<br><br>implementation<br>uses<br> ShlObj, ComObj, ActiveX<br> {$IFDEF DEBUG}<br> , DebugDLL<br> {$ENDIF DEBUG}<br> ;<br><br><br>{$R *.dfm}<br>//Mouse message routine<br>procedure TControlMessageHandler.NewWindowProc(var Message: TMessage);<br>begin<br>{$IFDEF DEBUG}<br> if (inttohex(Message.MSG, 4) <> 'B03F') and<br> (inttohex(Message.MSG, 4) <> '0200') and<br> (inttohex(Message.MSG, 4) <> '0020') and<br> (inttohex(Message.MSG, 4) <> '0084') then<br> SetTracemessages(true)<br> else<br> SetTracemessages(false);<br> // DebugMessage('Control ', Message.Msg);<br>{$ENDIF DEBUG}<br> if FParentForm.FPopup then<br> case Message.Msg of //<br> WM_SETCURSOR, CM_HITTEST:<br> begin<br> FParentForm.FLastHitTestTime := DateTimeToTimeStamp(now).time;<br> FParentForm.Capturing := false;<br> end;<br> WM_MOUSEMOVE:<br> begin<br> FParentForm.FLastHitTestTime := DateTimeToTimeStamp(now).time;<br> FParentForm.Capturing := false;<br> if FParentForm.FNCACTIVATE and not FParentForm.Capturing and FParentForm.FShowing then<br> begin<br> FParentForm.FNCACTIVATE := false;<br> FParentForm.ResetNCActivate;<br> end;<br> end;<br> end; // case<br> FOldWindowProc(Message);<br>end;<br><br>function TRSIPopupForm.InWindows:boolean;<br>var<br> lvo_Pos : TPoint;<br>begin<br> GetCursorPos(lvo_Pos);<br> result := PtInRect(Bounds(FRect.Left, FRect.Top,<br> FRect.Right - FRect.Left,<br> FRect.Bottom - FRect.Top),<br> lvo_Pos) ;<br>end;<br><br>function TRSIPopupForm.InWinControl:boolean;<br>var<br> lvo_Pos : TPoint;<br>begin<br> result := false;<br> GetCursorPos(lvo_Pos);<br> if not PtInRect(Bounds(FRect.Left, FRect.Top,<br> FRect.Right - FRect.Left,<br> FRect.Bottom - FRect.Top),<br> lvo_Pos) then exit;<br> result := FindVCLWindow(lvo_Pos) <> self;<br>end;<br><br>procedure TRSIPopupForm.ResetNCActivate;<br>var<br> lvo_pos : TPoint;<br>begin<br> GetCursorPos(lvo_pos);<br> SetCursorPos(FRect.right, FRect.bottom);<br> try<br> mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );<br> mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );<br> finally<br> SetCursorPos(lvo_pos.X, lvo_pos.y);<br> end;<br>end;<br><br><br><br>procedure TRSIPopupForm.WndProc(var Message: TMessage);<br>var<br> lvt_CData: TCopyDataStruct;<br> lvp_MessageContent: PChar;<br> lvs_ActionName : string;<br> i: Integer;<br> lvp_proc: procedure;<br>begin<br><br>{$IFDEF DEBUG}<br> if (inttohex(Message.MSG, 4) <> 'B03F') and<br> (inttohex(Message.MSG, 4) <> '0200') and<br> (inttohex(Message.MSG, 4) <> '0020') and<br> (inttohex(Message.MSG, 4) <> '0084') then<br> SetTracemessages(true)<br> else<br> SetTracemessages(false);<br>{$ENDIF DEBUG}<br> if FPopup then<br> begin<br> case Message.Msg of<br> WM_SETCURSOR, WM_MouseMove:<br> begin<br> FLastHitTestTime := DateTimeToTimeStamp(now).time;<br> Capturing := false;<br> end;<br> WM_LButtonDown, WM_RButtonDown:<br> begin<br> if (getcapture = FFormHandle) then<br> begin<br> PostMessage(FFormHandle, WM_CLOSE, 0, 0);<br> end;<br> end;<br> WM_NCActivate :<br> begin<br> if not boolean(Message.WParam) then<br> begin<br> FNCACTIVATE := true;<br> end<br> else<br> begin<br> FNCACTIVATE := false;<br> end;<br> end;<br> CM_ShowingChanged :<br> begin<br> if FShowing then<br> begin<br> FShowing := false;<br> Capturing := false;<br> FTimer.enabled := false;<br> FNCACTIVATE := false;<br> end;<br> end;<br> WM_ShowWindow :<br> begin<br> if boolean(Message.WParam) then<br> begin<br> FShowing := true ;<br> FTimer.Enabled := true;<br> end;<br> end;<br> end;<br> end;<br><br> case Message.Msg of<br> WM_WindowPosChanged :<br> begin<br> GetWindowRect(FFormHandle, FRect);<br> end;<br> WM_CopyData:<br> begin<br> lvt_CData := TWMCOPYDATA(Message).CopyDataStruct^;<br> lvp_MessageContent := lvt_CData.lpData;<br> if lvp_MessageContent[0] <> gcc_ActionCommand then<br> Exit;<br> i := 1;<br> lvs_ActionName := '';<br> while lvp_MessageContent <> #0 do<br> begin<br> lvs_ActionName := lvs_ActionName + lvp_MessageContent;<br> Inc(i);<br> end;<br> if lvs_ActionName = '' then<br> exit;<br> lvp_proc := MethodAddress(lvs_ActionName + 'Execute');<br> if Assigned(lvp_proc) then<br> lvp_proc;<br> end;<br> end;<br><br> inherited WndProc(Message);<br>end;<br><br>procedure TRSIPopupForm.InitAllControlMessageHandler(pvo_ParentControl : TControl);<br>var<br> I: Integer;<br>begin<br><br> if pvo_ParentControl.ComponentCount > 0 then<br> begin<br> for I := 0 to pvo_ParentControl.ComponentCount -1 do // Iterate<br> begin<br> if not (pvo_ParentControl.Components is TControl) then break;<br> InitControlMessageHandler(TControl(pvo_ParentControl.Components));<br> InitAllControlMessageHandler(TControl(pvo_ParentControl.Components));<br> end; // for<br> end; // while<br>end;<br><br>procedure TRSIPopupForm.InitControlMessageHandler(pvo_HandledControl : TControl);<br>var<br> lvo_Handler : TControlMessageHandler ;<br>begin<br> lvo_Handler := TControlMessageHandler.create;<br> with lvo_Handler do<br> begin<br> FOldWindowProc := pvo_HandledControl.WindowProc;<br> pvo_HandledControl.WindowProc := NewWindowProc;<br> FControl := pvo_HandledControl;<br> FParentForm := self;<br> end;<br><br> FHandlerList.Add(lvo_Handler);<br>end;<br><br>procedure TRSIPopupForm.FreeControlMessageHandler;<br>var<br> I: Integer;<br>begin<br> for I := FHandlerList.Count-1 downto 0 do // Iterate<br> begin<br> TControlMessageHandler(FHandlerList).FControl.WindowProc := TControlMessageHandler(FHandlerList).FOldWindowProc;<br> TControlMessageHandler(FHandlerList).FOldWindowProc := nil;<br> TControlMessageHandler(FHandlerList).FControl := nil;<br> TControlMessageHandler(FHandlerList).FParentForm := nil;<br> TControlMessageHandler(FHandlerList).free;<br> end; // for<br>end;<br><br>procedure TRSIPopupForm.SetCapturing(Value : boolean);<br>begin<br> <br> if FCapturing = Value then exit;<br> if Value then<br> begin<br> SetCapture(FFormHandle);<br> FCapturing := True;<br> end<br> else<br> begin<br> ReleaseCapture;<br> FCapturing := false;<br> end;<br>end;<br><br>//From routine<br><br>procedure TRSIPopupForm.CreateParams(var Params : TCreateParams);<br>begin<br> inherited CreateParams(Params);<br> Params.Style := WS_POPUP;<br> Params.ExStyle := Params.ExStyle OR WS_EX_TOPMOST ;<br> Params.Style := WS_THICKFRAME OR WS_POPUP OR WS_BORDER ;<br>// Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW ;<br>// Params.ExStyle := Params.ExStyle AND NOT WS_CAPTION ;<br>// Params.ExStyle := Params.ExStyle OR WS_EX_OVERLAPPEDWINDOW ;<br>// Params.ExStyle := Params.ExStyle OR WS_EX_TRANSPARENT;<br>end;<br><br>procedure TRSIPopupForm.TimerOnTimer(Sender: TObject);<br>begin<br> FTimer.enabled := false;<br> try<br> if (abs(DateTimeToTimeStamp(now).time - FLastHitTestTime) < 150) then<br> begin<br> Capturing := false;<br> exit;<br> end;<br> if InWindows then exit;<br> Capturing := true;<br> finally<br> FTimer.enabled := true;<br> end;<br>end;<br><br><br>procedure TRSIPopupForm.FormCreate(Sender: TObject);<br>var<br> i: Integer;<br> lvs_ActionName : string;<br> lvp_proc: procedure;<br>begin<br> visible := false;<br> left := screen.Width + 50;<br> <br> FToggle := false;<br> FPopup := true;<br><br> FFormHandle := self.Handle;<br><br> //create timer component<br> FTimer := TTimer.create(nil);<br> FTimer.interval := 100;<br> FTimer.OnTimer := TimerOnTimer;<br> FLastHitTestTime := DateTimeToTimeStamp(now).time;<br> FTimer.Enabled := Popup;<br><br> //Add mouse handler to all of controls<br> FHandlerList:= TObjectList.create;<br> InitAllControlMessageHandler(self);<br><br> //Checking execution parameter<br> for i := 1 to ParamCount do<br> begin<br> if copy(LowerCase(ParamStr(i)), 2, length(gcs_ActionParam)) = gcs_ActionParam then<br> begin<br> lvs_ActionName := trim(copy(LowerCase(ParamStr(i)), length(gcs_ActionParam) + 3, length(ParamStr(i))));<br> break;<br> end;<br> end;<br> if lvs_ActionName = '' then<br> exit;<br><br> //Invoking the action according the execution parameter<br> lvp_proc := MethodAddress(lvs_ActionName + 'Execute');<br> if Assigned(lvp_proc) then<br> lvp_proc;<br>end;<br><br>procedure TRSIPopupForm.FormDestroy(Sender: TObject);<br>begin<br> FreeControlMessageHandler;<br>// FHandlerList.free; //NTC<br> FTimer.free;<br>end;<br><br><br>procedure TRSIPopupForm.ShowFormByName(FormName : string);<br>var<br> lvo_FormClass : TPersistentClass;<br> lvo_Form :TForm;<br>begin<br> try<br> lvo_FormClass := FindClass(FormName) ;<br> except<br> ShowMessage(FormName + ' is not existed');<br> exit;<br> end;<br> if not Assigned(lvo_FormClass) then exit;<br> lvo_Form := TFormClass(lvo_FormClass).Create(Application);<br> lvo_Form.Show;<br> Application.ProcessMessages;<br> PostMessage(FFormHandle, WM_CLOSE, 0, 0);<br>end;<br><br>procedure TRSIPopupForm.Pan_TitleResize(Sender: TObject);<br>begin<br> Btn_Toggle.Left := Pan_Title.Width - 35;<br> Btn_Exit.Left := Pan_Title.Width - 20;<br>end;<br><br>procedure TRSIPopupForm.btn_ExitClick(Sender: TObject);<br>begin<br> PostMessage(FFormHandle, WM_Quit, 0, 0);<br>end;<br><br>procedure TRSIPopupForm.Pan_TitleMouseDown(Sender: TObject;<br> Button: TMouseButton; Shift: TShiftState; X, Y: Integer);<br>begin<br> if Button <> mbRight then<br> begin<br> end;<br>end;<br><br>procedure TRSIPopupForm.FormShow(Sender: TObject);<br>begin<br> btn_Toggle.Visible := FToggle ;<br>end;<br><br>end.<br>