2013-04-02 3 views
8

Sto provando a intercettare i clic del mouse da un altro programma. Sto facendo un plugin per il programma, che si sovrappone a un modulo trasparente sul programma e mostra informazioni aggiuntive. Quando clicco sulla parte trasparente del modulo posso fare clic su cose nel programma main. Non voglio che ciò accada (almeno non ogni volta - ci sono alcune parti in cui è consentito fare clic e alcune parti in cui non lo sei, ma questo non è il problema).Intercetta il clic del mouse da un altro programma

Il modo in cui sto facendo questo ora è utilizzando WH_MOUSE_LL, questo sta funzionando bene e posso mantenere il clic del mouse da ottenere al programma restituendo un valore diverso da zero (http://msdn.microsoft.com/en-gb/library/windows/desktop/ms644988(v=vs.85).aspx).

Il problema è che questo rende il mio programma principale in ritardo, non ho bisogno di ricevere notifiche per tutti i movimenti del mouse, voglio solo ricevere una notifica se l'utente ha effettivamente cliccato qualcosa. C'è un modo in cui posso limitare il WH_MOUSE_LL in modo che si attivi solo sui clic del mouse? (Il ritardo è non a causa di calcoli nel metodo MouseHookProc - è attualmente facendo nulla tranne che per la chiamata: CallNextHookEx(hHook, nCode, wParam, lParam).)

Ho cercato di risolvere questo problema utilizzando un hook globale (http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H) che si aggancia il WM_MOUSEACTIVATE Messaggio. L'idea era di collegare il WH_MOUSE_LL solo quando ho ricevuto una notifica WM_MOUSEACTIVATE. Sfortunatamente la notifica del clic WH_MOUSE_LL viene inviata prima del WM_MOUSEACTIVATE quindi non funziona.

EDIT:

@Nanda ecco il codice proc:

public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam) 
{ 
    return WindowUtility.CallNextHookEx(hHook, nCode, wParam, lParam); 
} 

Come si può vedere che non sto facendo molto con esso atm, ma ritardi già ...

@Cody Grey ho fatto un piccolo test per la gestione dei messaggi Modulo:

public class Form1 : Form 
{ 
    private TrackBar m_Trackbar; 

    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1()); 
    } 

    public Form1() 
    { 
     m_Trackbar = new System.Windows.Forms.TrackBar(); 
     m_Trackbar.LargeChange = 1; 
     m_Trackbar.Location = new System.Drawing.Point(5, 10); 
     m_Trackbar.Maximum = 100; 
     m_Trackbar.Size = new System.Drawing.Size(280, 40); 
     m_Trackbar.Value = 100; 
     this.Controls.Add(m_Trackbar); 

     m_Trackbar.Scroll += new System.EventHandler(this.m_TrackbarScroll); 
    } 


    private void m_TrackbarScroll(object sender, System.EventArgs e) 
    { 
     this.Opacity = ((Convert.ToDouble(m_Trackbar.Value))/100); 
    } 

    protected override void WndProc(ref Message m) 
    { 
     switch (m.Msg) 
     { 
      case 0x201: //WM_LBUTTONDOWN 
       Console.WriteLine("MouseButton Down!"); 
       //I could copy the Message over to the MainProgram with this right? 
       //SendMessage(MainProgramHwnd, m.Msg, m.WParam, m.LParam); 
       //This will also only work on an opacity higher than 0. 
       break; 
     } 
     base.WndProc(ref m); 
    } 
} 

Quando hai detto: "restituisci che è trasparente e lascia che sia indirizzato alla finestra sottostante"? Posso farlo usando SendMessage e fondamentalmente copiando il messaggio che ricevo nel mio metodo WndProc?

Per rendere le cose più complicate sto utilizzando anche questo modulo http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C. A mio parere questo mi consente di disegnare bitmap sul modulo che sono Anti Aliasing sullo sfondo. Con questa forma non sembra esserci modo di impostare l'opacità, poiché è sempre trasparente. C'è un modo migliore per disegnare bitmap su un modulo?

+1

Potrebbe essere che il tuo hook proc sta eseguendo troppe operazioni anche prima di verificare se il tipo di evento e il salvataggio su evento irrilevante. Porta il tuo hook proc a un solo richiamo CallNextHook (...) e aggiungi make incremental change. – nanda

+0

Perché il modulo di overlay non può ricevere solo tutti gli eventi del mouse che si verificano e filtrarli in modo appropriato? Se deve elaborarne uno, elaborarlo. In caso contrario, restituire che è trasparente e lasciarlo indirizzare alla finestra sottostante? Gli hook globali sono quasi sempre la soluzione sbagliata (anche se il suggerimento di nanda è buono se devi usarne uno). –

+0

Grazie ad entrambi per i vostri commenti, ho modificato la mia prima domanda con un po 'di codice e alcune informazioni aggiuntive. @Nanda Non sono esattamente sicuro di cosa intendi, sto attualmente restituendo solo CallNextHookEx ma questo è già in ritardo (ho aggiunto il mio codice proc al mio primo post). – VincentC

risposta

1

Si consiglia di esaminare Easyhook (http://easyhook.codeplex.com/) che consentirà di agganciare le chiamate API di Windows da un singolo processo piuttosto che per tutti i processi.