首页 > 解决方案 > wpf 应用程序 mvvm 监视器剪贴板

问题描述

我创建了一个控制台应用程序来监视剪贴板何时更改。它工作正常,代码显示在控制台代码部分的下面。

我现在的问题是尝试为使用 MVVM 的 WPF 应用程序执行此操作。我想我需要将 MainWindow 传递给我的视图模型,这是 MVVM 的正确方法吗?

更新

这是我尝试创建一个窗口。我已经读到我需要实现 HwndHost,这是我在 MyFirstWindow 类中完成的。我不确定如何隐藏窗口?

我假设在 ClipboardManager 下面的另一个类中,我需要创建 MyFirstWindow 的一个实例。但是我不确定要通过什么 HandleRef ?

 class MyFirstWindow : HwndHost
{

    IntPtr hwndHost;

    protected override HandleRef BuildWindowCore(HandleRef hwndParent)
    {
        hwndHost = IntPtr.Zero;
        hwndHost = CreateWindowEx(0, "static", "", WS_CHILD,
            0, 0, 50, 50, hwndParent.Handle,
            (IntPtr)HOST_ID,
            IntPtr.Zero, 0);

        return new HandleRef(this, hwndHost);
    }

    protected override void DestroyWindowCore(HandleRef hwnd)
    {            
        DestroyWindow(hwnd.Handle);
    }

    internal const int
      WS_CHILD = 0x40000000,
      WS_VISIBLE = 0x10000000,
      LBS_NOTIFY = 0x00000001,
      HOST_ID = 0x00000002,
      LISTBOX_ID = 0x00000001,
      WS_VSCROLL = 0x00200000,
      WS_BORDER = 0x00800000;

    [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)]
    internal static extern IntPtr CreateWindowEx(int dwExStyle,
                                          string lpszClassName,
                                          string lpszWindowName,
                                          int style,
                                          int x, int y,
                                          int width, int height,
                                          IntPtr hwndParent,
                                          IntPtr hMenu,
                                          IntPtr hInst,
                                          [MarshalAs(UnmanagedType.AsAny)] object pvParam);

    [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
    internal static extern bool DestroyWindow(IntPtr hwnd);
}

我在我的 WPF 应用程序中创建了下面的 ClipboardManager 类。

class ClipboardManager : IDisposable
{
    #region variable declaration
    /// <summary>
    /// Next clipboard viewer window 
    /// </summary>
    private IntPtr _hWndNextViewer;
    /// <summary>
    /// The <see cref="HwndSource"/> for this window.
    /// </summary>
    private HwndSource _hWndSource;
    private string _clipboardContent;
    #endregion

    #region property declaration
    public string ClipboardContent
    {
        get
        {
            return _clipboardContent;
        }
        set
        {
            _clipboardContent = value;
        }
    }
    #endregion

    public ClipboardManager()
    {
        hwnd = new MyFirstWindow();
        InitCBViewer();
    }

    private void InitCBViewer(System.Windows.Window wnd)
    {
        WindowInteropHelper wih = new WindowInteropHelper(wnd);
        _hWndSource = HwndSource.FromHwnd(wih.Handle);

        _hWndSource.AddHook(WinProc);   // start processing window messages
        _hWndNextViewer = Win32.SetClipboardViewer(_hWndSource.Handle);   // set this window as a viewer

    }

    private void CloseCBViewer()
    {
        // remove this window from the clipboard viewer chain
        Win32.ChangeClipboardChain(_hWndSource.Handle, _hWndNextViewer);

        _hWndNextViewer = IntPtr.Zero;
        _hWndSource.RemoveHook(this.WinProc);
    }

    private IntPtr WinProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        switch (msg)
        {
            case Win32.WM_CHANGECBCHAIN:
                if (wParam == _hWndNextViewer)
                {
                    // clipboard viewer chain changed, need to fix it.
                    _hWndNextViewer = lParam;
                }
                else if (_hWndNextViewer != IntPtr.Zero)
                {
                    // pass the message to the next viewer.
                    Win32.SendMessage(_hWndNextViewer, msg, wParam, lParam);
                }
                break;

            case Win32.WM_DRAWCLIPBOARD:
                // clipboard content changed
                if (Clipboard.ContainsText())
                {
                    ClipboardContent = Clipboard.GetText();
                }

                // pass the message to the next viewer.
                Win32.SendMessage(_hWndNextViewer, msg, wParam, lParam);
                break;
        }

        return IntPtr.Zero;
    }

    public void Dispose()
    {
        CloseCBViewer();
    }
}

赢得32班

 internal static class Win32
{
    /// <summary>
    /// The WM_DRAWCLIPBOARD message notifies a clipboard viewer window that 
    /// the content of the clipboard has changed. 
    /// </summary>
    internal const int WM_DRAWCLIPBOARD = 0x0308;

    /// <summary>
    /// A clipboard viewer window receives the WM_CHANGECBCHAIN message when 
    /// another window is removing itself from the clipboard viewer chain.
    /// </summary>
    internal const int WM_CHANGECBCHAIN = 0x030D;

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
}

标签: c#.netwpf

解决方案


推荐阅读