Probleme évenement click sur un ActiveX dans un UserControl [Résolu]

cs_fcolo 201 Messages postés mercredi 8 février 2006Date d'inscription 20 février 2007 Dernière intervention - 4 juil. 2006 à 09:20 - Dernière réponse : cs_fcolo 201 Messages postés mercredi 8 février 2006Date d'inscription 20 février 2007 Dernière intervention
- 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
Afficher la suite 

15 réponses

Répondre au sujet
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 5 juil. 2006 à 06:58
+3
Utile
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( ) );
        }
    }
}
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Lutinore
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 5 juil. 2006 à 17:14
+3
Utile
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( ) );
        }
    }
}
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Lutinore
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 4 juil. 2006 à 09:35
0
Utile
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
Commenter la réponse de cs_Bidou
cs_fcolo 201 Messages postés mercredi 8 février 2006Date d'inscription 20 février 2007 Dernière intervention - 4 juil. 2006 à 09:51
0
Utile
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
Commenter la réponse de cs_fcolo
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 4 juil. 2006 à 10:03
0
Utile
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
Commenter la réponse de cs_Bidou
cs_fcolo 201 Messages postés mercredi 8 février 2006Date d'inscription 20 février 2007 Dernière intervention - 4 juil. 2006 à 10:04
0
Utile
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
Commenter la réponse de cs_fcolo
cs_Bidou 5507 Messages postés dimanche 4 août 2002Date d'inscription 20 juin 2013 Dernière intervention - 4 juil. 2006 à 13:05
0
Utile
Désolé, je ne peux pas t'aider plus, mes connaissances d'activeX étant assez... restreintes

<hr size= "2" /> VC# forever
=13319
Commenter la réponse de cs_Bidou
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 5 juil. 2006 à 06:27
0
Utile
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.
Commenter la réponse de Lutinore
cs_fcolo 201 Messages postés mercredi 8 février 2006Date d'inscription 20 février 2007 Dernière intervention - 5 juil. 2006 à 09:19
0
Utile
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
Commenter la réponse de cs_fcolo
cs_fcolo 201 Messages postés mercredi 8 février 2006Date d'inscription 20 février 2007 Dernière intervention - 5 juil. 2006 à 09:28
0
Utile
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
Commenter la réponse de cs_fcolo
cs_fcolo 201 Messages postés mercredi 8 février 2006Date d'inscription 20 février 2007 Dernière intervention - 5 juil. 2006 à 09:47
0
Utile
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
Commenter la réponse de cs_fcolo
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 5 juil. 2006 à 16:40
0
Utile
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.
Commenter la réponse de Lutinore
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 5 juil. 2006 à 18:51
0
Utile
Finalement il semblerait que IMessageFilter fonctionne, je vais faire d'autres tests..
Commenter la réponse de Lutinore
Lutinore 3248 Messages postés lundi 25 avril 2005Date d'inscription 27 octobre 2012 Dernière intervention - 6 juil. 2006 à 05:16
0
Utile
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.
Commenter la réponse de Lutinore
cs_fcolo 201 Messages postés mercredi 8 février 2006Date d'inscription 20 février 2007 Dernière intervention - 6 juil. 2006 à 09:01
0
Utile
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
Commenter la réponse de cs_fcolo

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.