Solved

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

Posted on 2002-06-06
8
336 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
8 Comments
 
LVL 4

Expert Comment

by:nestorua
ID: 7061261
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
ID: 7061278
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
ID: 7061296
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
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 6

Author Comment

by:swift99
ID: 7061298
meikl: Thanks!  I'll check it out.
0
 
LVL 6

Author Comment

by:swift99
ID: 7061306
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
ID: 7061313
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
ID: 7061319
oops,
thanks for the grade,
hope you get it work

meikl ;-)
0
 
LVL 6

Author Comment

by:swift99
ID: 7061365
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

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

Suggested Solutions

Title # Comments Views Activity
Delphi application Soap connection 5 155
Run video youtube webbrowse 10 86
Unique identifier on a terminal server (rdp) 4 85
Firemonkey android show image from resource ? 1 72
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…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…

751 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