Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Place a border around windows/controls on mouseover

Posted on 2005-03-28
11
Medium Priority
?
198 Views
Last Modified: 2010-04-05
As the title suggest I am looking for a way to place a  border around any window/control on my computer when I move my mouse over it as long as I have the mouse button down and when I let go of the mouse button the border will disapper.

If it helps I am trying to make a SnagIT clone which for those of you that dont know is a screen capture utility and I have everything working fine except I would like to know what window/control I have the mouse over at the time in a visual manner so I know exactly what I am taking the screenshot of.

Hope that helps and thx for all replies in advance.
0
Comment
Question by:voodoo22
  • 7
  • 4
11 Comments
 
LVL 11

Expert Comment

by:pcsentinel
ID: 13650331
Not sure if this will help, but in order to find out what control you are over then you need to descend through all parents on a form, I use this for a slightly differnet reason but it may be of use

procedure TfrmMain.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
      lEn: boolean;
  lCon: tControl;
  lCon2: tControl;
  lp: tpoint;
  lc: tPoint;
  lGotLast: boolean;
begin
  if (Msg.Message = WM_LBUTTONDOWN) then
  begin
            lc:=Mouse.CursorPos;
            Handled:=true;
            lp:=ScreenToClient(lc);
            //get the control at this position
            lCon:=ControlAtPos(lp,true,true);
            //now need to descend through the controls until get to last control at mouse position
    if lCon is tWinControl then
    begin
                  lGotLast:=false;
                  while not lGotLast do
      begin
if lCon is tWincontrol then
          begin
            lp:=(lCon as TWinControl).ScreenToClient(lc);
            lCon2:=(lCon as TWinControl).ControlatPos(lp,true,true);
            if lCon2=nil then
              lGotLast:=true
            else
              lCon:=lCon2;
          end
          else
                lGotLast:=true;
end;
    end;
end;

this should leave you with lCon being the control under the mouse.


appmessage will override default handling if you put handled:=true; into the code.

As for drawing a border around a control its not straightforward as it depends on what the control is placed on, however you may be able to use the canvas of the form and use DrawRect using the info from the control returned from the above code


Hope this helps
0
 
LVL 11

Expert Comment

by:pcsentinel
ID: 13650360
Forgot to say that I have assumed that you dont want to actually process anything when you are is this mode i.e. you dont want the left click to actually do anything, so you add handled:=true into the code otherwise you could just use screen.activecontrol
0
 

Author Comment

by:voodoo22
ID: 13650517
thx for the info but I know how to get the control under the mouse part im just having difficulty with drawing a border around it.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 11

Expert Comment

by:pcsentinel
ID: 13650852
Try this

declarations

  private
        FLast: TWincontrol;
    procedure AppMessage(var Msg: TMsg; var Handled: Boolean);


procedure TForm1.FormCreate(Sender: TObject);
begin
      Application.OnMessage:=AppMessage;

end;



procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
      lEn: boolean;
  lCon: tControl;
  lCon2: tControl;
  lHelp: integer;
  lp: tpoint;
  lp2: tpoint;
  lc: tPoint;
  lGotLast: boolean;
  lRect: TRect;
  lDC: HDC;
  lPen: HPen;
begin
  if (Msg.Message = WM_LBUTTONDOWN) then
  begin
            lc:=Mouse.CursorPos;
            Handled:=true;
            lp:=ScreenToClient(lc);
            //get the control at this position
            lCon:=ControlAtPos(lp,true,true);
            //now need to descend through the controls until get to last control at mouse position
    if lCon is tWinControl then
    begin
                  lGotLast:=false;
                  while not lGotLast do
      begin
                              if lCon is tWincontrol then
          begin
            lp:=(lCon as TWinControl).ScreenToClient(lc);
            lCon2:=(lCon as TWinControl).ControlatPos(lp,true,true);
            if lCon2=nil then
              lGotLast:=true
            else
              lCon:=lCon2;
          end
          else
                lGotLast:=true;
                  end;
    end;
            if lCon<>nil then
    begin
      lp:=(lCon as TWinControl).Clienttoscreen(Point(0,0));
      lp2:=(lCon as TWinControl).Parent.Clienttoscreen(Point(0,0));
      lRect.Left:=lp.x-lp2.x-4;
      lREct.Top:=lp.y-lp2.y-4;
      lRect.Right:=lRect.Left+(lCon as TWinControl).Width+4;
      lRect.Bottom:=lRect.Top+(lCon as TWinControl).Height+4;
      if assigned(FLast) then
            FLast.Repaint;
      lDC:=GetDC((lCon as TWinControl).Parent.Handle);
      lPen:=CreatePen(PS_SOLID,4,clRed);
      SelectObject(lDc,lpen);
      Rectangle(lDC,lREct.Left,lRect.Top,lrect.Right,lrect.Bottom);
      Handled:=true;
      FLast:=(lCon as TWinControl).Parent;
    end;
  end;
end;


this was a quickie so you might need to do some work on screen refresh;
0
 
LVL 11

Expert Comment

by:pcsentinel
ID: 13651230
If you have got your own code for finding the control then you only need the section at the bottom i.e.

 private
       FLast: TWincontrol;

procedure DrawBorder(Con: TControl);
var
  lp: tpoint;
  lp2: tpoint;
  lc: tPoint;
  lGotLast: boolean;
  lRect: TRect;
  lDC: HDC;
  lPen: HPen;
begin
    if Con<>nil then
    begin
      lp:=(Con as TWinControl).Clienttoscreen(Point(0,0));
      lp2:=(Con as TWinControl).Parent.Clienttoscreen(Point(0,0));
      lRect.Left:=lp.x-lp2.x-4;
      lREct.Top:=lp.y-lp2.y-4;
      lRect.Right:=lRect.Left+(Con as TWinControl).Width+4;
      lRect.Bottom:=lRect.Top+(Con as TWinControl).Height+4;
      if assigned(FLast) then
           FLast.Repaint;
      lDC:=GetDC((Con as TWinControl).Parent.Handle);
      lPen:=CreatePen(PS_SOLID,4,clRed);
      SelectObject(lDc,lpen);
      Rectangle(lDC,lREct.Left,lRect.Top,lrect.Right,lrect.Bottom);
DeleteObject(lPen);
      FLast:=(Con as TWinControl).Parent;
    end;
  end;



Hope this helps
0
 

Author Comment

by:voodoo22
ID: 13651247
it doesn't appear to be donig nething. could you post the whole unit so I can see where Im making my mistakes thx.
0
 
LVL 11

Expert Comment

by:pcsentinel
ID: 13651374
-------------------------------------Unit Code-----------------------------------------

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Db, Grids, DBGrids, ADODB, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Panel1: TPanel;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
  private
        FLast: TWincontrol;
  public
    procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
  lCon: tControl;
  lCon2: tControl;
  lp: tpoint;
  lp2: tpoint;
  lc: tPoint;
  lGotLast: boolean;
  lRect: TRect;
  lDC: HDC;
  lPen: HPen;
begin
  if (Msg.Message = WM_LBUTTONDOWN) then
  begin
            lc:=Mouse.CursorPos;
            Handled:=true;
            lp:=ScreenToClient(lc);
            //get the control at this position
            lCon:=ControlAtPos(lp,true,true);
            //now need to descend through the controls until get to last control at mouse position
    if lCon is tWinControl then
    begin
                  lGotLast:=false;
                  while not lGotLast do
      begin
                              if lCon is tWincontrol then
          begin
            lp:=(lCon as TWinControl).ScreenToClient(lc);
            lCon2:=(lCon as TWinControl).ControlatPos(lp,true,true);
            if lCon2=nil then
              lGotLast:=true
            else
              lCon:=lCon2;
          end
          else
                lGotLast:=true;
                  end;
    end;
            if lCon<>nil then
    begin
      lp:=(lCon as TWinControl).Clienttoscreen(Point(0,0));
      lp2:=(lCon as TWinControl).Parent.Clienttoscreen(Point(0,0));
      lRect.Left:=lp.x-lp2.x-4;
      lREct.Top:=lp.y-lp2.y-4;
      lRect.Right:=lRect.Left+(lCon as TWinControl).Width+4;
      lRect.Bottom:=lRect.Top+(lCon as TWinControl).Height+4;
      if assigned(FLast) then
            FLast.Repaint;
      lDC:=GetDC((lCon as TWinControl).Parent.Handle);
      lPen:=CreatePen(PS_SOLID,4,clRed);
      SelectObject(lDc,lpen);
      Rectangle(lDC,lREct.Left,lRect.Top,lrect.Right,lrect.Bottom);
                  Handled:=true;
      FLast:=(lCon as TWinControl).Parent;
    end;
  end;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
      Application.OnMessage:=AppMessage;
end;

end.


------------------------------------------Form Code--------------------------------------

object Form1: TForm1
  Left = 1347
  Top = 231
  Width = 696
  Height = 480
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 64
    Top = 156
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
  end
  object Panel1: TPanel
    Left = 144
    Top = 304
    Width = 513
    Height = 129
    Caption = 'Panel1'
    TabOrder = 1
    object Button2: TButton
      Left = 36
      Top = 32
      Width = 75
      Height = 25
      Caption = 'Button2'
      TabOrder = 0
    end
  end
end

Note this is using the Appmessage code and the left click event so the control will be highlighted when you click on it but you can change how this works by modifying the message that is being responded to

Regards
0
 
LVL 11

Expert Comment

by:pcsentinel
ID: 13652784
How did you get on, if your having probs let me have ur controlundermouse code

Regards
0
 

Author Comment

by:voodoo22
ID: 13653480
I understand why it was not working before because we are not really thinking the same way and I did not know your code only worked for controls on the form and not system wide which is what I am looking for.

Basically I want it to add the border to ANY window/control on my computer (not just the controls on the form)  when i mouseover it (clicking is not really an option) hope that helps clear things up.

Also......

if you ever used the snagit program I talked about above you would see exactly the effect I am trying to accomplish. There is another program call "spy & capture utility" which is tool that gives you information about the winows your mouse is over and this program also uses this method so if you can find that program then you can see what I am talking about as well.
0
 
LVL 11

Accepted Solution

by:
pcsentinel earned 800 total points
ID: 13659989
Ok this should work its a bit of a cheat as its using a timer in your app but it works.

put

   private
        FLast2: HWND;

in declarations

then add a timer to your app with an interval of 10 and on the timer put

var
  lp: TPoint;
  lWnd: HWnd;
  lRect: TRect;
  lRect2: TRect;
  lDC: HDC;
  lPen: HPen;
  lBrush: HBrush;
  lbd: tagLOGBRUSH;
begin
      GetCursorPos(lp);
  lWnd:=WindowFromPoint(lp);
            if (lWnd<>null) and (lWnd<>GetDesktopWindow) and (lWnd<>FLAst2) then
    begin
      InvalidateRgn(FLast2,0,true);
      UpdateWindow(FLast2);
      lRect.Left:=lp.x;
      lRect.Top:=lp.y;
      Windows.GetClientRect(lWnd,lRect);
      lRect2.Left:=0;
      lRect2.Top:=0;
      lRect2.Right:=lRect.Right-lRect.Left-8;
      lRect2.Bottom:=lRect.Bottom-lRect.Top-8;
      lDC:=GetDC(lWnd);
      lPen:=CreatePen(PS_SOLID,4,clRed);
      lbd.lbStyle:=BS_HOLLOW;
      lbd.lbColor:=clRed;
      lbd.lbHatch:=HS_CROSS;
     lBrush:=CreateBrushIndirect(lbd);
      SelectObject(lDc,lpen);
      SelectObject(lDc,lBrush);
      Rectangle(lDC,lREct.Left,lRect.Top,lrect.Right,lrect.Bottom);
      DeleteObject(lPen);
      DeleteObject(lBrush);
      FLast2:=lWnd;
    end;
end;
0
 

Author Comment

by:voodoo22
ID: 13660204
timer is fine and thx for the help
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Enter Foreign and Special Characters Enter characters you can't find on a keyboard using its ASCII code ... and learn how to make a handy reference for yourself using Excel ~ Use these codes in any Windows application! ... whether it is a Micr…
Suggested Courses
Course of the Month15 days, 2 hours left to enroll

578 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question