Solved

non-rectangular controls on a form - how to detect mouse events

Posted on 2002-06-06
8
308 Views
Last Modified: 2010-04-04
I am building an application for viewing entities and relationships, and something that I expected to be trivial has instead been a very interesting problem.

Practically, the application GUI consists of a master form that contains other forms (representing entities) and a custom control that draws a line connecting two forms (representing associations).

The Delphi TControl methods that detect a mouse event are built on the assumption that all controls are rectangular.  On a screen showing a master entity and 50 owned entities with their relationships, I have 50 lines at varous angles extending from the master entity to the owned entities.

The math to detect whether a mouse click is on the line or not is trivial.  What I haven't figured out is how to get the mouse click event past the topmost control in a stack of overlapping rectangles - ie the control asks "Are you inside of me?  No -- let the next guy handle it" without creating an entirely new heirarchy from the TControl level down.

I can clone Borland's code and make the necessary changes (call it TFancyControl in the FancyControls unit if you like), but that seems like a kludge.

I am sure that this has been solved a hundred times, but my strength is in the business process rahter than in the GUI end of things.

Any assistance will be appreciated.

Thanks in advance.
0
Comment
Question by:swift99
  • 4
  • 3
8 Comments
 
LVL 4

Expert Comment

by:nestorua
Comment Utility
HI,
I think it may be done the following way:
obtain the coords of mouse pointer, convert them into coords
of the corresponding (maybe you must travel over all the controls you want to check) control and determine if the point
belong to this control.
Sincerely,
Nestorua.
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 100 total points
Comment Utility
get the devexpress forumlibrary (for free) at
www.devexpress.com

just register yourself in the forum there
you may get then a welcome-mail with a download link

in this library is a dfxConnector-component,
(connects two controls with a line)

gussing thats it what you need

meikl ;-)

0
 
LVL 6

Author Comment

by:swift99
Comment Utility
I have traced in the debugger and already determined that none of the available mouse events are fired on the parent form.  They are intercepted by the contained controls first.

This is intended for use in an enterprise environment, so I cannot guarantee that the associative representation control will always be on a form that I have defined.  The logic has to be self contained to the extent that the control will always behave correctly, at least within a Delphi VCL environment.

Hmmm ... Is there maybe a way to kick the mouse event back to the winProc?

The key to the whole thing is this method from the VCL, which (sadly) is private and is not virtual.

function TWinControl.ControlAtPos(const Pos: TPoint; AllowDisabled: Boolean): TControl;
var
  I: Integer;
  P: TPoint;
begin
  if FControls <> nil then
    for I := FControls.Count - 1 downto 0 do
    begin
      Result := FControls[I];
      with Result do
      begin
        P := Point(Pos.X - Left, Pos.Y - Top);
        if PtInRect(ClientRect, P) and    // *** This is the line that causes my problem ***
          ((csDesigning in ComponentState) and (Visible or
          not (csNoDesignVisible in ControlStyle)) or
          (Visible and (Enabled or AllowDisabled) and
          (Perform(CM_HITTEST, 0, Longint(PointToSmallPoint(P))) <> 0))) then
          Exit;
      end;
    end;
  Result := nil;
end;

function TWinControl.IsControlMouseMsg(var Message: TWMMouse): Boolean;
var
  Control: TControl;
  P: TPoint;
begin
  if GetCapture = Handle then
  begin
    Control := nil;
    if (CaptureControl <> nil) and (CaptureControl.Parent = Self) then
      Control := CaptureControl;
  end else
    Control := ControlAtPos(SmallPointToPoint(Message.Pos), False);
  Result := False;
  if Control <> nil then
  begin
    P.X := Message.XPos - Control.Left;
    P.Y := Message.YPos - Control.Top;
    Control.Perform(Message.Msg, Message.Keys, Longint(PointToSmallPoint(P)));
    Result := True;  // *** This line means that once a control is recognized there is ***
                             //       no chance of passing the event back to the WndProc for
                             //       someone else to handle.
  end;
end;
0
 
LVL 6

Author Comment

by:swift99
Comment Utility
meikl: Thanks!  I'll check it out.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 6

Author Comment

by:swift99
Comment Utility
meikl: Now I feel foolish - we have developers express tools here as a part of our standard setup.  :o(

It's 2:00 in the morning, that's my excuse.   :o)

lolrof
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
you should go into your bed and sleep a while,
if i'm awake so long time, then i'm near dead in head ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
oops,
thanks for the grade,
hope you get it work

meikl ;-)
0
 
LVL 6

Author Comment

by:swift99
Comment Utility
I'd love to get to bed, but I have to wait for this !@#$%^&*() report to print.  It takes 3 hours on a maxed out IBM 9000, and it's three days late.  I'm on call for the first time in this group, and we didn't even know our group owned this program when it blew up.  Since I'm not an MVS COBOL person by inclination, it's been interesting trying to debug and run the program.

The good news is that while it's running I have time to focus on other things.  The bad news is that while it's running I have to stick around so I can check it's output before I go to bed.   :o)

Isn't on-call duty fun?  <insert heavy does of sarcasm>
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

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…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

772 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now