c# - 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);
}
解决方案
推荐阅读
- sql - 在 SQL Server 2008 中将多个 SQL 行连接成单个列
- javascript - 在 reader.onload 完成执行后调用方法
- mysql - 除了查询中的选定结果外,如何在 mysql 中选择结果
- python - 从给定的矩阵值函数生成块矩阵
- linux - Linux 上的堆栈大小 - 有限堆栈大小与自动堆栈扩展
- loops - 我正在使用 if 语句,它应该打破循环。有人能帮我吗?(斯威夫特游乐场)
- node.js - Fedora 34 Silverblue - 网站开发容器
- go - 如何在使用 github.com/go-co-op/gocron 时删除以 LimitRunsTo(1) 选项开始的作业?
- sql-server - 使用 pyodbc 从 WSL2 连接到 Windows 上的 SQL Server - 连接超时
- postgresql - 我无法创建枚举类型的字段:sqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedObject) 类型“companytype”不存在