Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

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

Posted on 2002-06-06
8
Medium Priority
?
361 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
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 400 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

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

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…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …

886 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