如何拦截剪切板的消息并取得剪切板内容?(100分)

  • 主题发起人 主题发起人 spacepoint
  • 开始时间 开始时间
S

spacepoint

Unregistered / Unconfirmed
GUEST, unregistred user!
   我的想法是这样:我的程序驻在后台,一旦有人进行了剪切或复制操作,那我的程序将得知这一操作并判断当前剪切板的内容是否为文本,如果是文本则取得之。我有试过钩子但不知道用那种类型钩子,请DFW们帮忙,最好能有代码。
 
想法:<br>1,拦截按键Ctrl+C,Ctrl+X;<br>2,拦截 WM_PASTE 消息;<br>3,你说的钩子CopyHook;<br>//实现CopyHook接口<br>unit CopyMain; <br><br>interface <br><br>uses Windows, ComObj, ShlObj; <br><br>type <br>TCopyHook = class(TComObject, ICopyHook) <br>protected <br>function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PAnsiChar; <br>dwSrcAttribs: DWORD; pszDestFile: PAnsiChar; dwDestAttribs: DWORD): UINT; stdcall; <br>end; <br><br>TCopyHookFactory = class(TComObjectFactory) <br>protected <br>function GetProgID: string; override; <br>procedure ApproveShellExtension(Register: Boolean; const ClsID: string); <br>virtual; <br>public <br>procedure UpdateRegistry(Register: Boolean); override; <br>end; <br><br>implementation <br><br>uses ComServ, SysUtils, Registry; <br><br>{ TCopyHook } <br><br>// This is the method which is called by the shell for folder operations <br>function TCopyHook.CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; <br>pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD; pszDestFile: PAnsiChar; <br>dwDestAttribs: DWORD): UINT; <br>const <br>MyMessage: string = 'Are you sure you want to mess with "%s"?'; <br>begin <br>// confirm operation <br>Result := MessageBox(Wnd, PChar(Format(MyMessage, [pszSrcFile])), <br>'D4DG Shell Extension', MB_YESNO); <br>end; <br><br>{ TCopyHookFactory } <br><br>function TCopyHookFactory.GetProgID: string; <br>begin <br>// ProgID not needed for shell extension <br>Result := ''; <br>end; <br><br>procedure TCopyHookFactory.UpdateRegistry(Register: Boolean); <br>var <br>ClsID: string; <br>begin <br>ClsID := GUIDToString(ClassID); <br>inherited UpdateRegistry(Register); <br>ApproveShellExtension(Register, ClsID); <br>if Register then <br>// add shell extension clsid to CopyHookHandlers reg entry <br>CreateRegKey('directory/shellex/CopyHookHandlers/' + ClassName, '', <br>ClsID) <br>else <br>DeleteRegKey('directory/shellex/CopyHookHandlers/' + ClassName); <br>end; <br><br>procedure TCopyHookFactory.ApproveShellExtension(Register: Boolean; <br>const ClsID: string); <br>// This registry entry is required in order for the extension to <br>// operate correctly under Windows NT. <br>const <br>SApproveKey = 'SOFTWARE/Microsoft/Windows/CurrentVersion/Shell Extensions/Approved'; <br>begin <br>with TRegistry.Create do <br>try <br>RootKey := HKEY_LOCAL_MACHINE; <br>if not OpenKey(SApproveKey, True) then Exit; <br>if Register then WriteString(ClsID, Description) <br>else DeleteValue(ClsID); <br>finally <br>Free; <br>end; <br>end; <br><br>const <br>CLSID_CopyHook: TGUID = '{66CD5F60-A044-11D0-A9BF-00A024E3867F}'; <br><br>initialization <br>TCopyHookFactory.Create(ComServer, TCopyHook, CLSID_CopyHook, <br>'D4DG_CopyHook', 'D4DG Copy Hook Shell Extension Example', <br>ciMultiInstance, tmApartment); <br>end. <br>
 
注册剪贴板监视链,稍后贴上源程序
 
to FeelingLoad<br>&nbsp; &nbsp; 仔细看了您的代码,没明白是什么意思,新建一个工程,把这个Unit连上去也没什么作用。它的原理是怎么样的,怎么使用,能说得清楚一点吗?<br>to 特尔斐<br>&nbsp; &nbsp; 期待着您的程序。
 
http://www.zbbbs.com/index.asp?classid=4&amp;Nclassid=7<br>这里有段代码<br>这个东西在DFW的全文检索里很多,找一下就根本不必提这个问题
 
我的系统不如为什么就是不能检索,提说缺少什么什么对象
 
ok,解决了
 
我许一个诺言就得了80分^&amp;^ ,看来得贴点代码了。<br>其实在WIN32中监视剪贴板非常容易,只在用到两个API函数,处理<br>两条消息。<br>两个API:<br>SetClipboardViewer<br>将一个窗口设为剪贴板查看器<br><br>ChangeClipboardChain<br>改变剪贴板监视链,一般用于取消你注册的剪贴板查看器<br><br>两条消息:<br>WM_CHANGECBCHAIN<br>当剪贴板监视链发生改变时,这条消息将发送到剪贴板查看器窗口<br>应该在这里记录它的LPARAM(一个窗口句柄,指向下一个贴板查看<br>器窗口)备用。<br><br>WM_DRAWCLIPBOARD<br>当系统剪贴板发生改变时,这条消息将发送到剪贴板查看器窗口,<br>在这里面处理所有的监视逻辑。<br><br>下面是实现代码:<br><br>unit main;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs, DB, ADODB, ComCtrls, ToolWin, ImgList, ActnList, ExtCtrls,<br>&nbsp; StdCtrls, DBCtrls, Menus;<br><br>type<br>&nbsp; TfrmMain = class(TForm)<br>&nbsp; &nbsp; //...省略无关的代码<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; //...省略无关的代码<br>&nbsp; &nbsp; procedure OnWM_CHANGECBCHAIN(var Msg:TMessage);message WM_CHANGECBCHAIN;<br>&nbsp; &nbsp; procedure OnWM_DRAWCLIPBOARD(var Msg:TMessage);message WM_DRAWCLIPBOARD;<br>&nbsp; &nbsp; //...省略无关的代码<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; &nbsp; function HasText:boolean;<br>&nbsp; &nbsp; function GetText:string;<br>&nbsp; &nbsp; function HasPicture(var Format:Word):boolean;<br>&nbsp; &nbsp; //...省略无关的代码<br>&nbsp; end;<br><br>var<br>&nbsp; frmMain: TfrmMain;<br><br>implementation<br><br>{$R *.dfm}<br><br>procedure TfrmMain.FormCreate(Sender: TObject);<br>begin<br>&nbsp; &nbsp;//将本窗体注册到剪贴板监视链中<br>&nbsp; &nbsp;FNextClipBrdViewerWnd :=SetClipboardViewer(Handle);<br>&nbsp; &nbsp;FWatchClipbrd :=true;<br>&nbsp; &nbsp;FAutoSaveClipBrdText :=true;<br>end;<br><br>procedure TfrmMain.FormDestroy(Sender: TObject);<br>begin<br>&nbsp; &nbsp;//还原剪贴板监视链<br>&nbsp; &nbsp;ChangeClipboardChain(Handle,FNextClipBrdViewerWnd);<br>end;<br><br>//处理剪贴板消息<br>procedure TfrmMain.OnWM_DRAWCLIPBOARD(var Msg: TMessage);<br>const<br>&nbsp; OldText:string=''; &nbsp; //类型常量(相当于VB中的静态变量),要开编译器选项<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//即Syntax options中的Assignable typed constants要<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//选中才能通过编译<br>var<br>&nbsp; s:string;<br>begin<br>&nbsp; &nbsp;if not FWatchClipbrd then exit;<br>&nbsp; &nbsp;//这里只取文本,其实你可以监视任何放入剪贴板的东东<br>&nbsp; &nbsp;<br>&nbsp; &nbsp;s :=GetText;<br><br>&nbsp; &nbsp;if OldText&lt;&gt;s then<br>&nbsp; &nbsp;begin &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; //reBox为一文本框<br>&nbsp; &nbsp; &nbsp; reBox.PasteFromClipboard;<br>&nbsp; &nbsp; &nbsp; OldText :=s;<br>&nbsp; &nbsp;end;<br>end;<br><br>procedure TfrmMain.OnWM_CHANGECBCHAIN(var Msg: TMessage);<br>begin<br>&nbsp; &nbsp;FNextClipBrdViewerWnd :=msg.LParam; //更新下一个剪贴板查看窗口句柄<br>end;<br><br>function TfrmMain.GetText: string;<br>var<br>&nbsp; Data:THandle;<br>begin<br>&nbsp; &nbsp;Result:='';<br>&nbsp; &nbsp;OpenClipboard(Application.Handle);<br>&nbsp; &nbsp;try<br>&nbsp; &nbsp; &nbsp; Data :=GetClipboardData(CF_TEXT);<br>&nbsp; &nbsp; &nbsp; if Data&lt;&gt;0 then Result:=PChar(GlobalLock(Data));<br>&nbsp; &nbsp;finally<br>&nbsp; &nbsp; &nbsp; if Data&lt;&gt;0 then GlobalUnlock(Data);<br>&nbsp; &nbsp; &nbsp; CloseClipboard;<br>&nbsp; &nbsp;end;<br>end;<br><br>function TfrmMain.HasText: boolean;<br>begin<br>&nbsp; &nbsp;Result :=IsClipboardFormatAvailable(CF_TEXT);<br>end;<br><br>procedure TfrmMain.SetAutoSaveClipBrdText(const Value: boolean);<br>begin<br>&nbsp; &nbsp;FAutoSaveClipBrdText := Value;<br>end;<br><br>procedure TfrmMain.SetWatchClipbrd(const Value: boolean);<br>begin<br>&nbsp; FWatchClipbrd := Value;<br>end;<br><br>function TfrmMain.HasPicture(var Format:Word): boolean;<br>var<br>&nbsp; fmt:Word;<br>begin<br>&nbsp; &nbsp;OpenClipboard(Application.Handle);<br>&nbsp; &nbsp;try<br>&nbsp; &nbsp; &nbsp;fmt:=EnumClipboardFormats(0);<br>&nbsp; &nbsp; &nbsp;while fmt&lt;&gt;0 do<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; if TPicture.SupportsClipboardFormat(fmt) then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Format :=fmt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Result :=true;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exit;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; &nbsp; fmt:=EnumClipboardFormats(fmt);<br>&nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp;finally<br>&nbsp; &nbsp; &nbsp;CloseClipboard;<br>&nbsp; &nbsp;end;<br>end;<br><br>end.<br>
 
后退
顶部