Componentes - criar borda de foco ao redor do selecionado

Top  Previous  Next

// Comentario do Junior - é bom e funciona. O problema é o foco em tela com

// RadioGroup e TabSheet, fica meio feio

 

Herbert J. Beemster's article Give Your Editbox Some Attention! derived an edit box that display an extra border when it has

focus. Great idea, but a real pain in the #!$e deriving a new control every time you wanted to add that functionality. 

 

That set me thinking about an idea i had ages ago - to trap delphi's Cn_FocusChanged message, and draw a border around any

control that has just received the focus. 

 

Attached is the control TucsFocus (delphi 3) - basically it waits for a control to send out a Cn_FocusChanged message, and

then resizes itself and positions inself *under* the focused control to produce a border effect. 

 

To place the TucsFocus under and control on a form, it is necessary to change it's parent - this caused a problem because when

the message handler is active, the parent is looping through it's controls list to notify all it's children, so changing the parent in the

message handler resulted in an index out of bounds exception.  To handle this i had to post a WM_USER message to the

control which would then be processed after all of the parent's children had been notified.  It is the WM_USER message

handler that does all the work

 

I've added two properties: Color (naturally) and BorderSize (the width of the border). 

 

I dare say it could be improved - for instance not using the WM_USER message - but i hope some of you find a use for it. 

 

Eamonn Mulvihill 

Consultancy and programing services 

 

 

 

     unit ucsFocus; 

 

     { 

 

     TucsFocus by Eamonn Mulvihill of Update Computer Services. 

 

     This control uses delphi's notification message cm_FocusChanged 

     to follow the focus around the form.  When a control receives 

     focus, it paints a bold border around it, basically by resixing 

     itself and placing itself behind the focused control. 

 

     This source is free for any use, but i would appreciate a mention 

     in any controls that are derived from it. 

 

     } 

 

     interface 

 

     uses 

       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; 

 

     type 

       TucsFocus = class(TCustomControl) 

       private 

         fBorderSize : integer; 

       protected 

         procedure CMFocusChanged(var msg:TCMFocusChanged); message Cm_FocusChanged; 

         procedure MSGAfterFocus(var msg:TCMFocusChanged); message WM_USER

         procedure Paint; override; 

       public 

         constructor Create(AOwner:TComponent); override; 

       published 

         property Color; 

         property BorderSize:integer read fBorderSize write fBorderSize; 

       end

 

     procedure Register; 

 

     implementation 

 

     //set property defaults 

     constructor TucsFocus.Create(AOwner:TComponent); 

     begin

     inherited create(AOwner); 

     width  := 20

     height := 20

     color  := clBtnShadow; 

     BorderSize := 3

     end

 

     //paint the control 

     procedure TucsFocus.Paint; 

     begin

     inherited; 

     with canvas do 

       begin

       //draw filled rectangle 

       brush.color := color; 

       FillRect(ClientRect); 

       //a little extra in design mode 

       if csDesigning in ComponentState then 

         begin

         pen.color := clBlack; 

         rectangle(0,0,width,height); 

         font.name := 'Arial'

         font.size := 11

         font.style := [fsBold]; 

         TextOut(6,1,'F'); 

         end

       end

     end

 

     //Delphi is currently looping throught the parent's controls list. 

     //Canging the parent here will cause an exception, so post a USER 

     //message, which will be processed after all controls have been 

     //processed. 

     procedure TucsFocus.CMFocusChanged(var msg:TCMFocusChanged); 

     var UserMsg:TMessage; 

     begin

     UserMsg := TMessage(msg); 

     UserMsg.msg := WM_USER

     PostMessage(handle,WM_USER,UserMsg.wParam,UserMsg.lParam); 

     end

       

 

     //OK, now we can move the TucsFocus, size it and change the parent too! 

     procedure TucsFocus.MSGAfterFocus(var msg:TCMFocusChanged); 

     var rect :TRect; 

     begin

     try 

       //calculate size and position 

       rect := msg.Sender.BoundsRect; 

       rect.left   := rect.left   - BorderSize; 

       rect.top    := rect.top    - BorderSize; 

       rect.right  := rect.right  + BorderSize; 

       rect.bottom := rect.bottom + BorderSize; 

       BoundsRect := rect; 

       //and change parents 

       parent := msg.Sender.parent; 

       SendToBack; 

       finally 

         inherited; 

       end

     end

       

 

     procedure Register; 

     begin 

       RegisterComponents('U.C.S', [TucsFocus]); 

     end

 

     end.