使用一些下载工具比如FlashGet、DuDu下载器,通常有一个选项叫做监视剪贴板,如果发现指定类型的后缀名,则自动开始下载,监视剪贴板的小技巧很有实用价值。
下面就说说监视剪贴板的小技巧。
Windows系统使用list或者是chain来保存当剪贴板的数据发生变化的时候要求被通知到的一些窗口。
每一次当剪贴板的数据发生变化的时候,这个list的第一个窗口收到一个WM_DRAWCLIPBOARD系统消息, 该窗口可以查询剪贴板数据的相关信息。这个非常简单的过程,我们只要遵循下面几条说明,调用相关的win32API函数就行了。
(1)
protected static extern int SetClipboardViewer(
int hWndNewViewer);
当调用
SetClipboardViewer函数的时候,需要传递接收这个消息(
WM_DRAWCLIPBOARD)的窗口句柄作为参数,
SetClipboardViewer 返回当前观察链中下一个窗口句柄,通常程序需要保存这个值,因为我们需要把消息传递给观察链中的下一个窗口。
(2)处理
WM_DRAWCLIPBOARD 消息
重载窗体的WndProc方法,处理消息,参看程序
(3)处理
WM_CHANGECBCHAIN消息,因为每个处理
WM_DRAWCLIPBOARD消息的窗口必须担负把消息传递个下个观察链窗口的任务。
(4)处理
WM_CHANGECBCHAIN消息,当一个窗口把自己从观察链移出时候的消息。该移出过程(程序结束时)通过调用
Win32ChangeClipboardChain函数完成。
代码:
[DllImport(
"
User32.dll
"
)]
protected
static
extern
int
SetClipboardViewer(
int
hWndNewViewer);
![None.gif](/Images/OutliningIndicators/None.gif)
[DllImport(
"
User32.dll
"
, CharSet
=
CharSet.Auto)]
public
static
extern
bool
ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
![None.gif](/Images/OutliningIndicators/None.gif)
[DllImport(
"
user32.dll
"
, CharSet
=
CharSet.Auto)]
public
static
extern
int
SendMessage(IntPtr hwnd,
int
wMsg, IntPtr wParam, IntPtr lParam);
IntPtr nextClipboardViewer;
protected
override
void
WndProc(
ref
System.Windows.Forms.Message m)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
// defined in winuser.h
const int WM_DRAWCLIPBOARD = 0x308;
const int WM_CHANGECBCHAIN = 0x030D;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
switch(m.Msg)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case WM_DRAWCLIPBOARD:
DisplayClipboardData();
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
break;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
case WM_CHANGECBCHAIN:
if (m.WParam == nextClipboardViewer)
nextClipboardViewer = m.LParam;
else
SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
break;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
default:
base.WndProc(ref m);
break;
}
}
private
void
Form1_Closed(
object
sender, System.EventArgs e)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
ChangeClipboardChain(this.Handle,NextClipHwnd);
//从观察链中删除本观察窗口
SendMessage(NextClipHwnd,WM_CHANGECBCHAIN,this.Handle,NextClipHwnd);
//将WM_DRAWCLIPBOARD消息传递到下一个观察链中的窗口
}
void
DisplayClipboardData()
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
try
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
IDataObject iData = new DataObject();
iData = Clipboard.GetDataObject();
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
if (iData.GetDataPresent(DataFormats.Rtf))
richTextBox1.Rtf = (string)iData.GetData(DataFormats.Rtf);
else if (iData.GetDataPresent(DataFormats.Text))
richTextBox1.Text = (string)iData.GetData(DataFormats.Text);
else
richTextBox1.Text = "[Clipboard data is not RTF or ASCII Text]";
}
catch(Exception e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show(e.ToString());
}
}