Probleme évenement click sur un ActiveX dans un UserControl

Résolu
cs_fcolo Messages postés 201 Date d'inscription mercredi 8 février 2006 Statut Membre Dernière intervention 20 février 2007 - 4 juil. 2006 à 09:20
cs_fcolo Messages postés 201 Date d'inscription mercredi 8 février 2006 Statut Membre Dernière intervention 20 février 2007 - 6 juil. 2006 à 09:01
Bonjour,

J'utilise l'ActiveX de VLC (logiciel de capture video) pour capturer le flux vidéo d'une caméra IP.
Dans le logiciel que je réalise, je permet d'afficher plusieur vidéo.
De ce fait, j'avais plusieurs ActiveX dans la form (à la volée).
J'ai placé l'activeX dans un UserControl pour ajouter des fonctions.

Maintenant, ce que je veux faire c'est de pouvoir sélectionner une vidéo pour faire des action dessus.
Malheureusement, l'ActiveX de VLC ne possède pas d'évenement clic ou contextMenu.
Ce que je voudrais, c'est qu'au niveau de l'UserControl, je puisse réceptionner l'évenement clic comme si l'ActiveX n'était pas présent.
C'est à dire que même si l'utilisateur clique sur l'activeX, ce soit l'évenement clic de l'UserControl qui soit levé.

Savez vous si c'est faisable?
Pouvez vous me donner des indications pour que je puisse résoudre mon problème?

Merci

f.colo

15 réponses

Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
5 juil. 2006 à 06:58
Avec un hook ça passe..

( Il ne faut pas faire n'importe quoi dans le hook sinon tu ralentis le système. )

using System;
using System.Drawing;
using System.Security;
using System.Windows.Forms;
using System.Runtime.InteropServices;


using AxAXVLC;
using AXVLC;


namespace Hook
{
    public class MainForm : Form
    {
        #region Win32


        [ StructLayout( LayoutKind.Sequential ) ]
        private struct MSLLHOOKSTRUCT
        {
            public int X;
            public int Y;
            public int Data;
            public int Flags;
            public int Time;
            public UIntPtr Extra;
        }


        [ DllImport( "user32.dll", SetLastError = true ), SuppressUnmanagedCodeSecurity ]
        private static extern IntPtr SetWindowsHookEx( int hook, HookProc callback, IntPtr module, uint threadID );


        [ DllImport( "user32.dll", SetLastError = true ), SuppressUnmanagedCodeSecurity ]
        private static extern bool UnhookWindowsHookEx( IntPtr hHook );


        [ DllImport( "user32.dll" ), SuppressUnmanagedCodeSecurity ]
        private static extern IntPtr CallNextHookEx( IntPtr hHook, int code, UIntPtr wParam, IntPtr lParam );


        private delegate IntPtr HookProc( int code, UIntPtr wParam, IntPtr lParam );
       
        private const int WM_LBUTTONDOWN = 0x0201;
        private const int WH_MOUSE_LL = 14;
        private const int HC_ACTION = 0;


        #endregion Win32


        private IntPtr hHook = IntPtr.Zero;
        private HookProc hookProc = null;


        private AxVLCPlugin axVLC = null;


        public MainForm( )
        {
            this.Text = "ProjectVLC";
            this.ClientSize = new Size( 384, 288 );


            axVLC = new AxVLCPlugin( );
           
            Button b = new Button( );
            b.Text = "Play/Stop";
            b.Dock = DockStyle.Bottom;
            b.Click += delegate
            {
                if ( !axVLC.Playing )
                {
                    axVLC.addTarget( "c:\\video.mpg", null, VLCPlaylistMode.VLCPlayListInsert, 1 );
                    axVLC.play( );
                }
                else
                {
                    axVLC.stop( );
                }
            };


            this.Controls.AddRange( new Control[ ] { axVLC, b } );
        }


        protected override void OnLoad( EventArgs e )
        {
            base.OnLoad( e );


            hookProc = new HookProc( LowLevelMouseProc );
            hHook = SetWindowsHookEx( WH_MOUSE_LL, hookProc, Marshal.GetHINSTANCE( this.GetType( ).Module ), 0 );
               
            if ( hHook == IntPtr.Zero ) // Le hook ne s'installe pas en mode DEBUG.
                MessageBox.Show( "Impossible d'installer le hook.", "Erreur" );
        }


        protected override void OnFormClosed( FormClosedEventArgs e )
        {
            base.OnFormClosed( e );


            if ( hHook != IntPtr.Zero )
            {
                if ( !UnhookWindowsHookEx( hHook ) )
                    MessageBox.Show( "Impossible de désinstaller le hook.", "Erreur" );


                hHook = IntPtr.Zero;
                hookProc = null;
            }
        }


        private IntPtr LowLevelMouseProc( int code, UIntPtr wParam, IntPtr lParam )
        {
            if ( code == HC_ACTION && axVLC != null )
            {
                unsafe
                {
                    MSLLHOOKSTRUCT* p = ( MSLLHOOKSTRUCT* )lParam;


                    if ( axVLC.RectangleToScreen( axVLC.Bounds ).Contains( p->X, p->Y ) && ( int )wParam == WM_LBUTTONDOWN )
                    {
                        MessageBox.Show( "Left Click" );
                    }
                }
            }
           
            return CallNextHookEx( hHook, code, wParam, lParam );
        }
       
        [ STAThread ]
        private static void Main( )
        {
            Application.Run( new MainForm( ) );
        }
    }
}
3
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
5 juil. 2006 à 17:14
Je pense que cette solution est meilleure mais elle est disponible à partir de Windows XP seulement.

using System;
using System.Drawing;
using System.Security;
using System.Windows.Forms;
using System.Runtime.InteropServices;


using AxAXVLC;
using AXVLC;


namespace RawHook
{
    public class MainForm : Form
    {
        #region Win32


        [ StructLayout( LayoutKind.Sequential ) ]
        private struct RAWINPUTDEVICE
        {
            public ushort usagePage;
            public ushort usage;
            public uint flags;
            public IntPtr hWndTarget;
        }


        [ DllImport( "USER32.DLL", SetLastError = true ) ]
        private static extern bool RegisterRawInputDevices
        (
            [ In ] RAWINPUTDEVICE[ ] rawInputDevices,
            uint numDevices,
            uint size
        );


        private const int WM_INPUT = 0x00FF;
        private const int RIDEV_REMOVE = 0x00000001;


        #endregion Win32


        private AxVLCPlugin axVLC = null;


        public MainForm( )
        {
            this.Text = "ProjectVLC";
            this.ClientSize = new Size( 384, 288 );


            axVLC = new AxVLCPlugin( );
           
            Button b = new Button( );
            b.Text = "Play/Stop";
            b.Dock = DockStyle.Bottom;
            b.Click += delegate
            {
                if ( !axVLC.Playing )
                {
                    axVLC.addTarget( "c:\\video.mpg", null, VLCPlaylistMode.VLCPlayListInsert, 1 );
                    axVLC.play( );
                }
                else
                {
                    axVLC.stop( );
                }
            };


            this.Controls.AddRange( new Control[ ] { axVLC, b } );


            RegisterMouse( );
        }


        private void RegisterMouse( )
        {
            RAWINPUTDEVICE[ ] devices = new RAWINPUTDEVICE[ 1 ];
            devices[ 0 ].usagePage = 0x01; // HID Mouse Usage Page.
            devices[ 0 ].usage = 0x02; // HID Mouse Usage.
            devices[ 0 ].hWndTarget = this.Handle;


            RegisterRawInputDevices( devices, ( uint )devices.Length, ( uint )Marshal.SizeOf( typeof( RAWINPUTDEVICE ) ) );
        }


        private void UnregisterMouse( )
        {
            RAWINPUTDEVICE[ ] devices = new RAWINPUTDEVICE[ 1 ];
            devices[ 0 ].usagePage = 0x01; // HID Mouse Usage Page.
            devices[ 0 ].usage = 0x02; // HID Mouse Usage.
            devices[ 0 ].flags = RIDEV_REMOVE;


            RegisterRawInputDevices( devices, ( uint )devices.Length, ( uint )Marshal.SizeOf( typeof( RAWINPUTDEVICE ) ) );
        }


        protected override void Dispose( bool disposing )
        {
            try
            {
                UnregisterMouse( );
            }
            finally
            {
                base.Dispose( disposing );
            }
        }


        protected override void WndProc( ref Message m )
        {
            if ( m.Msg == WM_INPUT )
            {
                if
                (
                    // Rajoute le test du focus ici
                    //MyUsercontrol.ContainsFocus &&
                    Control.MouseButtons == MouseButtons.Left &&
                    axVLC.RectangleToScreen( axVLC.Bounds ).Contains( Control.MousePosition )
                )
                {
                    MessageBox.Show( "Left Click !" );
                }
            }


            base.WndProc( ref m );
        }
       
        [ STAThread ]
        private static void Main( )
        {
            Application.Run( new MainForm( ) );
        }
    }
}
3
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
4 juil. 2006 à 09:35
Hi,
Je ne sais pas si c'est exactement ce que tu recherches, mais cette source de coq pourrait éventuellement t'aider (je ne sais pas si ça marche avec activeX)

<hr size= "2" /> VC# forever
=13319
0
cs_fcolo Messages postés 201 Date d'inscription mercredi 8 février 2006 Statut Membre Dernière intervention 20 février 2007 2
4 juil. 2006 à 09:51
Effectivement, ca semble interressant.
Malheureusement, il ne détecte que le MouseMove, MouseEnter et MouseLeave car il ne tient compte que du Message WM_MOUSEMOVE.

Je ne sais pas si on peut surcharger sa classe en y intégrant les clics:
        private const int WM_MOUSEMOVE = 0x200;
        private const int WM_LBUTTONDOWN = 0x201;
        private const int WM_RBUTTONDOWN = 0x204;
        private const int WM_MBUTTONDOWN = 0x207;
        private const int WM_LBUTTONUP = 0x202;
        private const int WM_RBUTTONUP = 0x205;
        private const int WM_MBUTTONUP = 0x208;
        private const int WM_LBUTTONDBLCLK = 0x203;
        private const int WM_RBUTTONDBLCLK = 0x206;
        private const int WM_MBUTTONDBLCLK = 0x209;

Je vais essayer de m'y lancer mais sans grande conviction, je ne suis pas assez callé pour ca.

Merci pour le lien, je ne valide pas car il ne résoud pas directeemnt mon problème.

Merci

f.colo
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
4 juil. 2006 à 10:03
Ben il peut détecter les autres, suffit de les ajouter :

        public event MouseEventHandler MouseMove;
        public event EventHandler MouseEnter;
        public event EventHandler MouseLeave;
        public event EventHandler MouseHover;
        public event EventHandler MouseUp;
        public event EventHandler MouseDown;
        private const int WM_MOUSEMOVE = 0x0200;
        private const int WM_MOUSEHOVER = 0x02A1;
        private const int WM_LBUTTONDOWN = 0x0201;
        private const int WM_LBUTTONUP = 0x0202;

<hr size="2" /> VC# forever
=13319
0
cs_fcolo Messages postés 201 Date d'inscription mercredi 8 février 2006 Statut Membre Dernière intervention 20 février 2007 2
4 juil. 2006 à 10:04
Donc pour info, la modification n'a pas été si compliqué :).
J'ai rajouté quelque ligne:
         private const int WM_LBUTTONUP = 0x202;

         public event EventHandler Click;

         protected virtual void OnClick()
         {
             if (this.Click != null)
                 this.Click(this._container, EventArgs.Empty);
         }

             if (m.Msg == WM_LBUTTONUP)
             {
                 this.OnClick();
             }

Et j'ai appliqué sa methode pour l'itégrer à mon UserControl:
                    ContainerLevelMouseEventsMessageFilter vlcLevelEvents = new ContainerLevelMouseEventsMessageFilter(vlcCamControler1);
                    Application.AddMessageFilter(vlcLevelEvents);
                    vlcLevelEvents.Click += new EventHandler(vlcLevelEvents_Click);

Mais ca fait pareil qu'avant, lorsque je n'affiche aucune vidéo, le clic sur l'UserControl est interprété, mais dès que la capture de la vidéo est lancée, je ne peut plus rien faire.
C'est assez facheux comme truc, je ne sais pas comment je vais m'en sortir.

f.colo
0
cs_Bidou Messages postés 5487 Date d'inscription dimanche 4 août 2002 Statut Membre Dernière intervention 20 juin 2013 61
4 juil. 2006 à 13:05
Désolé, je ne peux pas t'aider plus, mes connaissances d'activeX étant assez... restreintes

<hr size= "2" /> VC# forever
=13319
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
5 juil. 2006 à 06:27
Salut, normalement IMessageFilter fonctionne bien avec les ActiveX mais là je viens de tester et c'est un peu spécial l'ActiveX VLC utilise en interne plusieurs fenêtres, "VLC Video Window", "DirectX Video" etc, ". et une fois la vidéo lancée on voit bien les messages avec SPY++ mais l'application ne reçoit plus de messages, en tout cas ils ne passent plus par IMessageFilter.. l'ActiveX doit utiliser la souris en mode exclusif quelque chose comme ça.
0
cs_fcolo Messages postés 201 Date d'inscription mercredi 8 février 2006 Statut Membre Dernière intervention 20 février 2007 2
5 juil. 2006 à 09:19
Effectivement, ca fonctionne comme ca, heureusement que vous etes là, je ne trouverai jamais un truc comme ca moi, merci.

Par contre c'est assez chiant, avec ton exemple, lorsque je clique sur le OK du messageBox le hock considère que je suis sur lui, donc il m'en ouvre trop.

Maintenant que j'ai la base je vais essayé de remagnier tout ca pour ouvrir un context menu sur un clic droit.

Merci à nouveau.

f.colo
0
cs_fcolo Messages postés 201 Date d'inscription mercredi 8 février 2006 Statut Membre Dernière intervention 20 février 2007 2
5 juil. 2006 à 09:28
Tu utilise le hook bas niveau de la souris, pour capturer le clic dans tout windows (MSDN):

private const int WH_MOUSE_LL = 14;
hHook = SetWindowsHookEx( WH_MOUSE_LL, hookProc, Marshal.GetHINSTANCE( this.GetType( ).Module ), 0 );

Est ce fait expres ou est ce que je peut utilise le public const int WH_MOUSE = 7; ?
Afin d'éviter que ca prenne en compte le clic meme sur le MessageBox.

f.colo
0
cs_fcolo Messages postés 201 Date d'inscription mercredi 8 février 2006 Statut Membre Dernière intervention 20 février 2007 2
5 juil. 2006 à 09:47
Donc j'ai testé avec le WH_MOUSE = 7; mais ca ne fait rien de plus.
J'ai alors regardé sur VCL avait le focus avant de déclancher une action dans le hook et ca fonctionne :).

private const int WM_RBUTTONUP = 0x205;

        private IntPtr LowLevelMouseProc(int code, UIntPtr wParam, IntPtr lParam)
        {
            if (code == HC_ACTION && this.VLC != null)
            {
                if(this.VLC.ContainsFocus)
                unsafe
                {
                    MSLLHOOKSTRUCT* p = (MSLLHOOKSTRUCT*)lParam;

                    if (this.VLC.RectangleToScreen(this.VLC.Bounds).Contains(p->X, p->Y) && (int)wParam == WM_RBUTTONUP)//WM_LBUTTONDOWN
                    {
                        MessageBox.Show("rigth Click");
                    }
                }
            }

            return CallNextHookEx(hHook, code, wParam, lParam);
        }
-------------------------------------------------------------------------

Une autre question, pkoi tu détecte le click sur le MouseDown et non pas sur un MouseUp?

f.colo
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
5 juil. 2006 à 16:40
Effectivement j'utilise le hook global on peut peut être avoir un comportement plus précis avec un hook local mais dans ce cas il faut changer plusieurs choses dont la structure MSLLHOOKSTRUCT etc..

MouseDown ou MouseUp comme tu veux, c'était juste pour l'exemple.

Si j'ai le temps je vais tester autre chose sans le hook.
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
5 juil. 2006 à 18:51
Finalement il semblerait que IMessageFilter fonctionne, je vais faire d'autres tests..
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
6 juil. 2006 à 05:16
J'ai compris ce que se passe, l'ActiveX capture la souris à chaque fois qu'il récupère le focus, ça marche avec IMessageFilter, faut lui faire relâcher la souris à chaque fois qu'il récupère le focus, mais comme en interne il utilise des fenêtres DirectX, c'est pas simple, autant utiliser les méthodes précédentes.
0
cs_fcolo Messages postés 201 Date d'inscription mercredi 8 février 2006 Statut Membre Dernière intervention 20 février 2007 2
6 juil. 2006 à 09:01
Merci pour ta solution, mais malheureusement, mon programme va plutot être utilisé sous un environement win2000.
En tout cas, merci de te prendre la tete pour moi, car tu m'a donné des solutions que je n'aurai jamais sus trouver seul.

f.colo
0
Rejoignez-nous