C# .NET Event Handling (Mouse Events)

Archives Forums/Blitz3D SDK Programming/C# .NET Event Handling (Mouse Events)

Daz(Posted 2007) [#1]
Hi all,

I am starting to play around with the B3D SDK under C# .NET.

I am having a few problems with handling events.

For keyboard input, I have cheated a little by overriding the main OnKeyDown handler
i.e.
        protected override void OnKeyDown(KeyEventArgs e)
        {
            my_keydown(e);
            base.OnKeyDown(e);
        }

        void my_keydown(KeyEventArgs e)
        {
            if (e.KeyCode.Equals(Keys.Escape))
            {
                MessageBox.Show("You pressed escape");
            }

            if (e.Alt && e.KeyCode == Keys.A)
            {
                MessageBox.Show("Alt + A");
            }
        }


I cannot do the same with the mouse events though:
e.g. If I use this code:

        protected override void OnMouseClick(MouseEventArgs e)
        {
            my_mouseclick(e);
            base.OnMouseClick(e);
        }

        void my_mouseclick(MouseEventArgs e)
        {
            MessageBox.Show("Mouse Click Event");
        }


The Mouse Click Event message is only shown when I click on an area which is outside of the panel control (which houses the SDK rendering window).

None of the panel control's events (e.g. MouseEnter, MouseLeave) work either.

This seems to suggest the B3D render window "swallows" the mouse events before .NET.

Any ideas how to get around this? I have read about the SetBlitz3DEventCallback method, but I have no idea how to use it from within C# .NET.

Cheers.

Daz.


Rone(Posted 2007) [#2]
Hi,

Are the event not raised automatically?
I think the normal way is so:
private void BBControl_MouseDown(object sender, MouseEventArgs e)
        {
            int tmpX = e.X;
            int tmpY = e.y;
        }

        private void BBControl_MouseMove(object sender, MouseEventArgs e)
        {
            int tmpX = e.X;
            int tmpY = e.y;
        }

And if that not work, I would try it in the folloing way:
(There you have transform the global coordinates)

        private void BBControl_MouseMove(object sender,  MouseEventArgs e)
        {
            BeginInvoke(new System.EventHandler(MouseMove_Event(sender, e)));

        }

        private void BBControl_MouseUp(object sender,  MouseEventArgs e)
        {
            BeginInvoke(new System.EventHandler(MouseUp_Event(sender, e)));

        }

        private void BBControl_MouseDown(object sender,  MouseEventArgs e)
        {
            BeginInvoke(new System.EventHandler(MouseDown_Event(sender, e)));
        }

       private void MouseDown_Event(object sender, System.EventArgs e)
        {
            int tmpX = Cursor.Position.X - this.Parent.Location.X  - BBControl.Location.X;
            int tmpY = Cursor.Position.Y - this.Parent.Location.Y  - BBControl.Location.Y;
        }

        private void MouseUp_Event(object sender, System.EventArgs e)
        {
            int tmpX = Cursor.Position.X - this.Parent.Location.X - BBControl.Location.X;
            int tmpY = Cursor.Position.Y - this.Parent.Location.Y - BBControl.Location.Y;
        }

        private void MouseMove_Event(object sender, System.EventArgs e)
        {
            int tmpX = Cursor.Position.X - this.Parent.Location.X - BBControl.Location.X;
            int tmpY = Cursor.Position.Y - this.Parent.Location.Y - BBControl.Location.Y;
        }


But in the second way I think it must be adjusted because the position is offset...
Unfortunatly I cant test it...

Regards
Rone


Daz(Posted 2007) [#3]
Hi Rone,

Thanks for the suggestions. I gave what you suggested a try, unfortunately, to no avail.

The problem is the Blitz3d SDK doesn't actually return a control/isn't a control object. All you can do is render the Blitz3d screen to a standard .net container control e.g. picture box, panel etc.

I am not entirely sure what is going on but if you move the mouse over the Blitz SDK rendering window, the underlying container control (i.e. the picture box, panel etc.) does not receive the mouse event(s).

On top of this, the Blitz rendering window doesn't register any values when using the likes of the bb.MouseHit() or bb.MouseDown() methods.

Here is some example code to illustrate my point
        private void Control_MouseDown(System.Object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Control control = (Control)sender;
            if (control.Capture)
            {
                toolStripStatusLabel1.Text = control.Name + " has captured the mouse";
            }
        }


I assign this method to the MouseDown event for both the form and the picture box container control. The statusBar label gets updated when clicking on the form but it doesn't display anything when clicking on the picture box control.

I have tried everything else within my (little) knowledge of C# .NET but I cannot get it to work.

So, I think it may either be a case of there is a bug within the SDK DLL or trying to handle mouse events when rendering to a container control will never work.


Rone(Posted 2007) [#4]
Hmm,

what is with the form which hold your control in that Blitz3d renders?
It could also recieve the mouseevents and from there you can
invoke the mouseevent-handler in your control with global coordinates...only an idea

By the way:
You can't change the label.text in that way, because the Control_MouseDown() runns in another threat, I think.
You must do it with a helper variable or BeginInvoke()!

I would like to test it, but have no SDK until yet...I'm still thiking about to by it. Is the c# wrapper already integrated?


dynaman(Posted 2007) [#5]
> I'm still thiking about to by it. Is the c# wrapper already integrated?

a C# wrapper comes with the download. There is a small example to show how to use it as well. (very small, but it gets the job done)


dynaman(Posted 2007) [#6]
Found a way around the problem using VB, should work for C#.

Put a panel over top of your rendering surface, then check for events on the panel.


Daz(Posted 2007) [#7]
Hi Dynaman,

Can you please just run through exactly what you did as I cannot seem to get it to work? I am also trying with VB.NET.

Here is what I did:

1) Put panel1 on the form which will be used to store the rendering surface.

2) Put panel2 on top of panel 1.

The problem with this is that when running the program, the form appears grey because panel2 is taking priority over panel1 i.e. panel2 being drawn over panel1.

Did you create panel2 inside of panel1 so panel1 is a container for panel2? Was there any specific properties you had to set on either panel in order to get it to work? Did you have to apply any code?

Cheers,
Daz.


dynaman(Posted 2007) [#8]
I created 2 panels, both with the form as the parent (double click on the panel and let forms set them up as normal). Then I placed the first panel where I wanted it, then I placed the second panel over top of it.

I did not need to set any properties. If you want I can email the form portion of the code to you. It is done in VS 2005.


Daz(Posted 2007) [#9]
Hi Dynaman,

I started from scratch again and this time it worked. What a really cool, and yet so simple, solution to the problem. To be honest, I would have never thought of that.

I owe you a pint!!!! :)

Cheers,
Daz.


dynaman(Posted 2007) [#10]
> I owe you a pint!!!! :)

No problem, you helped me a ton with that # Develop tool - it saved me a bunch of work (and allowed me to help you with your problem)