2013-04-17 2 views
0

J'ai une application WPF (écrite en C#) qui a un contrôle Listview qui défile parfaitement avec la molette de la souris lorsque l'application est nette. Toutefois, lorsque l'application n'est pas au point, même lorsque le pointeur de la souris est sur la zone d'affichage de la liste de l'application, la liste ne défile pas. Je continue à voir les effets liés à mousehover sur l'application mais aucun événement mousewheel n'est reçu. Ceci est en ligne avec la façon dont la plupart des autres applications fonctionnent sur mon bureau, mais certains d'entre eux (comme Facebook Messenger) supportant le défilement sans focus que je voudrais imiter dans mon application WPF. J'ai cherché des forums MSDN et Stackoverflow et vu plusieurs solutions pour Windows Forms mais ils ont été des questions posées il y a plus de 5 ans et je me demandais si quelqu'un a réussi à le faire relativement facilement sur .net 4.5 et peut me diriger vers possible solutions.WPF Listview ne défile pas (avec molette de la souris) lorsque l'application n'est pas mise au point

--- --- Modifier

j'ai pu progresser dans une certaine mesure, cela grâce à ce fil C# ListView mouse wheel scroll without focus

Voici comment mon la fonction qui reçoit la molette de la souris semble

private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam) 
{ 
if (nCode >= 0 && 
MouseMessages.WM_MOUSEWHEEL == (MouseMessages)wParam) 
     { 
      MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); 
      Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y); 
      Console.WriteLine((short)((hookStruct.mouseData)>>16));     
      MouseWheelEventArgs myArgs = new MouseWheelEventArgs(System.Windows.Input.Mouse.PrimaryDevice, (int)hookStruct.time, (short)((hookStruct.mouseData)>>16)); 
      myMainFrame.SidePanelControl.ScrollTheListView(myArgs); 
      } 
     return CallNextHookEx(_hookID, nCode, wParam, lParam); 
    } 

Comme vous pouvez le voir, j'initialise une instance MouseWheelEventArgs et possède les attributs time, delta et mouse device.

Comment puis-je transmettre cet événement mousewheel à mon scrollviewer listview?

Répondre

2

Géré pour que cela fonctionne. Voici ma classe. Tout ce qu'on doit faire pour utiliser la classe est

  1. Initialiser InterceptMouse passant l'application/listview/etc pointeur
  2. Démarrer interceptant la souris lorsque l'application est pas au point, mais l'événement mouseenter correspondant a eu lieu.
  3. Tant que l'événement est mousewheel, le scrollviewer de listview recevra l'événement mouseWheel.
  4. Arrêtez d'intercepter la souris lorsque l'application est activée ou que l'appel de souris est appelé.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 
using System.Windows.Interop; 
using System.Windows.Forms; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 
using System.Windows.Input; 
using System.Diagnostics; 
using System.Windows.Forms.Integration; 
namespace myApp.HelperClasses 
{ 
    public class InterceptMouse 
    { 
     public static System.Windows.Controls.ListView myListview; 
     private static LowLevelMouseProc _proc = HookCallback; 
     private static IntPtr _hookID = IntPtr.Zero; 


     public InterceptMouse(System.Windows.Controls.ListView myListviewParam) 
     { 
      myListview = myListviewParam; 
     } 

     public static void StartIntercepting() 
     { 
      _hookID = SetHook(_proc); 
     } 
     public static void StopIntercepting() 
     { 
      UnhookWindowsHookEx(_hookID); 
     } 

     private static IntPtr SetHook(LowLevelMouseProc proc) 
     { 
      using (Process curProcess = Process.GetCurrentProcess()) 
      using (ProcessModule curModule = curProcess.MainModule) 
      { 
       return SetWindowsHookEx(WH_MOUSE_LL, proc, 
        GetModuleHandle(curModule.ModuleName), 0); 
      } 
     } 

     private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); 


     private static IntPtr HookCallback(
      int nCode, IntPtr wParam, IntPtr lParam) 
     { 
      if (nCode >= 0 && 
       MouseMessages.WM_MOUSEWHEEL == (MouseMessages)wParam) 
      { 
       MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); 
       //Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y + "," + hookStruct.mouseData); 

       var delta = (short)((hookStruct.mouseData) >> 16); 
       var mouse = InputManager.Current.PrimaryMouseDevice; 
       var args = new MouseWheelEventArgs(mouse, Environment.TickCount, delta); 
       args.RoutedEvent = WindowsFormsHost.MouseWheelEvent; 

       Decorator border = VisualTreeHelper.GetChild(myListview, 0) as Decorator; 
       // Get scrollviewer 
       ScrollViewer scrollViewer = border.Child as ScrollViewer; 
       scrollViewer.RaiseEvent(args); 
      } 
      return CallNextHookEx(_hookID, nCode, wParam, lParam); 
     } 



     private const int WH_MOUSE_LL = 14; 

     private enum MouseMessages 
     { 
      WM_LBUTTONDOWN = 0x0201, 
      WM_LBUTTONUP = 0x0202, 
      WM_MOUSEMOVE = 0x0200, 
      WM_MOUSEWHEEL = 0x020A, 
      WM_RBUTTONDOWN = 0x0204, 
      WM_RBUTTONUP = 0x0205 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct POINT 
     { 
      public int x; 
      public int y; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct MSLLHOOKSTRUCT 
     { 
      public POINT pt; 
      public uint mouseData; 
      public uint flags; 
      public uint time; 
      public IntPtr dwExtraInfo; 
     } 

     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr SetWindowsHookEx(int idHook, 
      LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId); 

     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool UnhookWindowsHookEx(IntPtr hhk); 

     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, 
      IntPtr wParam, IntPtr lParam); 

     [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr GetModuleHandle(string lpModuleName); 
    } 
} 
Questions connexes