Hi friends,
enclosed is a simple class which provides the message handling for an UserControl that hooks into the Clipboard chain.
Is it in any way critical that when the UserControl gets destroyed, a call to ChangeClipboardChain is made to inform the chain that our chlipboard viewer is about to be removed?
If for example the UserControl resides inside an AutoCAD Palette Set, this could be effected by a handler for PaletteSetDestroy, which then calls Unhook() below.
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace MyClipBoard
{
class WinInvoke
{
[DllImport("user32.dll")]
public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
[DllImport("user32.dll")]
public static extern IntPtr GetClipboardViewer();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
}
public class CbPalette : UserControl
{
// Constants for Windows API calls
public const int WM_DRAWCLIPBOARD = 0x308;
public const int WM_CHANGECBCHAIN = 0x30D;
// Handle for next clipboard viewer
public IntPtr _nxtCbVwrHWnd;
public CbPalette()
{
_nxtCbVwrHWnd = WinInvoke.SetClipboardViewer(this.Handle);
}
public void Unhook()
{
WinInvoke.ChangeClipboardChain(this.Handle, _nxtCbVwrHWnd);
}
protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
// The clipboard has changed
case WM_DRAWCLIPBOARD:
WinInvoke.SendMessage(this._nxtCbVwrHWnd, m.Msg, m.WParam, m.LParam);
break;
// Another clipboard viewer has removed itself
case WM_CHANGECBCHAIN:
if (m.WParam == _nxtCbVwrHWnd)
_nxtCbVwrHWnd = m.LParam;
else
WinInvoke.SendMessage(_nxtCbVwrHWnd, m.Msg, m.WParam, m.LParam);
break;
}
base.WndProc(ref m);
}
}
}
(No, I don't tell anyone where this idea came from... since there was no unhooking.)
Cheers, Thorsten