怎么从剪贴板获取复制的Outlook邮件/附件,保存为文件

如何从剪贴板获取复制的Outlook邮件/附件,保存为文件?
本帖最后由 Dreamia 于 2013-12-08 15:03:07 编辑
目前我正在设计一个申请系统,需要用户将审批邮件和附件关联到对应申请表单,上传到系统中。
系统是通过FTP上传文件的,使用idFTP控件。目前我只能使用OpenDialog,用户将邮件另存为文件,然后在系统中点击按钮,浏览选中该文件,然后上传。这样就多了一个把邮件另存为文件的动作,用户抵触很大。
我希望做到的是,在Outlook选中邮件或者附件->Ctrl+C复制->在系统中Ctrl+V(或者点按钮),系统自动识别,然后从剪贴板获取文件流,上传到FTP。
现在主要问题卡在文件流的获取上面。
以下测试代码:

procedure TForm1.btn1Click(Sender: TObject);
var
  P:PWideChar;
  i:Integer;
begin
  txt1.Clear;    //txt1是一个mmotext
  if Clipboard.FormatCount>0 then
  try
    Clipboard.Open;
    for i := 0 to Clipboard.FormatCount-1 do
    begin
      GetClipboardFormatName(Clipboard.Formats[i],P,255);
      txt1.Lines.Add(IntToStr(Clipboard.Formats[i]) + #9 + P);  //剪贴板格式代码+格式注册名称
    end;
  finally
    Clipboard.Close;
  end;
end;

当选择邮件或者附件时,运行结果:
49161 DataObject
49453 FileGroupDescriptorW
49452 FileGroupDescriptor
49711 RenPrivateItem
49451 FileContents
49171 Ole Private Data
经查,FileGroupDescriptorW可以表明剪贴板中有此类文件。但是问题来了:
1,这个代码49453居然是会变的,昨天是这个,今天开机测试,又变49464了。对于VB,可以用Clipboard.ContainsData("FileGroupDescriptor")来判断;但是Delphi应该如何用格式名称来获取对应的代码,并判断是否存在?我目前只能通过遍历剪贴板中所有格式的名称是否有"FileGroupDescriptorW"来判断;
2,如果有FileGroupDescriptorW格式,该如何从剪贴板中获取到对应的文件流?该如何从文件流中获取文件名/文件格式信息,以便保存为对应格式文件?
3,如何让窗体本身接受Ctrl+V事件并在事件发生时,进行指定操作?我如下代码不起作用:

private
  procedure WMPaste(var Message: TMessage); message WM_PASTE;

procedure TForm1.WMPaste(var Message: TMessage);
var
  S:string;
  i,NumFiles:Integer;
  DataHandle: THandle;
  buffer: Array [0..MAX_PATH] of Char;
begin
  if IsClipboardFormatAvailable(CF_HDROP) then
  begin
    Clipboard.Open;
    try
      DataHandle:=Clipboard.GetAsHandle(CF_HDROP);
      If DataHandle<>0 Then
      Begin
        NumFiles:=DragQueryFile(DataHandle,$FFFFFFFF, nil,0);
        for i:= 0 to NumFiles - 1 do
        begin
         buffer[0] := #0;
         DragQueryFile(DataHandle,i,buffer,sizeof(buffer));
         ShowMessage(buffer);
        end;
      end;
    finally
      Clipboard.close;
    end;
  end;
end;

请大家多多指教,非常感谢!

参考:VB版:http://social.msdn.microsoft.com/Forums/vstudio/en-US/affcf9cd-704d-4ea2-b80b-4c09062af72d/how-extract-an-outlook-attachment-from-the-clipboard-?forum=wpf
C#版:http://*.com/questions/11041005/getting-multiple-outlook-attachments-from-clipboard
------解决方案--------------------
俺也没做过此类应用,稍微帮你搜了搜,具体得自己查MSDN
http://www.delphigroups.info/2/5d/414002.html
shlobj 单元中的 IDataObject 接口提供了QueryGetData方法,通过QueryGetData可以获取到一个FileGroupDescriptor 文件组描述结构体的指针,由此来判断

3,如何让窗体本身接受Ctrl+V事件并在事件发生时,进行指定操作?
可以对该窗体定义热键ctrl+v,当该热键按下时做处理


MSDN中也提供了一个综合各种剪贴板操作的示例

Example of a Clipboard Viewer
The following example shows a simple clipboard viewer application. 

HINSTANCE hinst; 
UINT uFormat = (UINT)(-1); 
BOOL fAuto = TRUE; 
 
LRESULT APIENTRY MainWndProc(hwnd, uMsg, wParam, lParam) 
HWND hwnd; 
UINT uMsg; 
WPARAM wParam; 
LPARAM lParam; 

    static HWND hwndNextViewer; 
 
    HDC hdc; 
    HDC hdcMem; 
    PAINTSTRUCT ps; 
    LPPAINTSTRUCT lpps; 
    RECT rc; 
    LPRECT lprc; 
    HGLOBAL hglb; 
    LPSTR lpstr; 
    HBITMAP hbm; 
    HENHMETAFILE hemf; 
    HWND hwndOwner; 
 
    switch (uMsg) 
    { 
        case WM_PAINT: 
            hdc = BeginPaint(hwnd, &ps); 
 
            // Branch depending on the clipboard format. 
 
            switch (uFormat)