关于复制HTML源文件到剪贴板格式

// sClipFormat: array[TConvType] of string = ('HTML Format', 'Rich Text Format');
// TConvType = (ctHTML, ctRTF);
 
procedure TfrmMain.AddToClip(const psFormatText, psText: string;
 const ConvType: TConvType);
var
 bIsAddToClip, bIsAddSourceCodeTextOfFormat: boolean;
begin
 bIsAddToClip := mmConvAfterAddToClip.Checked;       // 是否加入剪贴板
 bIsAddSourceCodeTextOfFormat := mmAddToClipTextIsSourceCode.Checked;
    // 加到剪贴板文本格式是否源码
 
 if not bIsAddToClip then
    Exit;
 
 if bIsAddSourceCodeTextOfFormat then
 begin
    if ConvType = ctHTML then
      AddFormatToClipBoard(
        GetHTMLClipFormat(psFormatText),   // 转换 HTML 源码为剪贴板格式
        psFormatText,                                  // 剪贴板文本格式放 HTML 源码
        sClipFormat[ConvType])                    // 注册到剪贴板的格式
    else
      AddFormatToClipBoard(
        psFormatText,
        psFormatText,
        sClipFormat[ConvType]);
 end
 else
 begin
    if ConvType = ctHTML then
      AddFormatToClipBoard(
        GetHTMLClipFormat(psFormatText),   // 转换 HTML 源码为剪贴板格式
        psText,                                            // 剪贴板文本格式放未转换前源码
        sClipFormat[ConvType])                   // 注册到剪贴板的格式
    else
      AddFormatToClipBoard(
        psFormatText,
        psText,
        sClipFormat[ConvType]);
 end;
end ;
 
procedure AddFormatToClipBoard(const psFormatText,psText,psFormat:string);
var
 iFormatTextLen,iTextLen :integer;
 uFormat :UINT;
 hData: THandle;
 pData: Pointer; 
begin
  // psFormat :
  // Rich Text Format = 多信息文本格式到剪贴板
  // HTML Format = 网页格式到剪贴板
 
 iFormatTextLen := Length(psFormatText);   // StrLen
 iTextLen := Length(psText);
 
 Clipboard.Open;
 try
    EmptyClipboard;
   
    // Add Format = psFormat
    if iFormatTextLen > 0 then
    begin
      uFormat := RegisterClipboardFormat(PChar(psFormat));
      hData := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, iFormatTextLen + 1 );
      try
        pData := GlobalLock(hData);
        try
          Move(PChar(psFormatText)^,pData^,iFormatTextLen + 1 );
          SetClipboardData(uFormat,hData);
        finally
          GlobalUnlock(hData);
        end;
      except
        GlobalFree(hData);
        raise;
      end;
    end;
 
    // Add Text Format = CF_TEXT
    if iTextLen > 0 then
    begin
      hData := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, iTextLen + 1 );
      try
        pData := GlobalLock(hData);
        try
          Move(PChar(psText)^,pData^,iTextLen + 1 );
          SetClipboardData(CF_TEXT,hData);
        finally
          GlobalUnlock(hData);
        end;
      except
        GlobalFree(hData);
        raise;
      end;
    end
   
 finally
    Clipboard.Close;
 end;
end ;
                                                      
function GetHTMLClipFormat(const psInput: string):string;
const
 CRLF = System.sLineBreak;
 sClipHead =
    'Version:1.0'                 + CRLF +  // 1.0 版本
    'StartHTML:%.10d'        + CRLF +  // 从第一字符到 DocHand 前一字符数量
    'EndHTML:%.10d'         + CRLF +  // 整个内容数量  ( 注:这里的数量最大 10 位数 )
    'StartFragment:%.10d'  + CRLF +  // 第一个字符到 <!--StartFragment--> 数量
    'EndFragment:%.10d'   + CRLF +  // 第一个字符到 <!--EndFragment--> 数量
    'StartSelection:%.10d' + CRLF +  // =StartFragment
    'EndSelection:%.10d'   + CRLF +  // =EndFragment
    'SourceURL:%s'          + CRLF;   // 来源地址 http://xx.xx.xx/xxx.htm -- about:blank
 sDocHead =                                // html 文档中开始  -- 假设原来还没有
    '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">' + CRLF;
 
 sStartFragment = '<!--StartFragment-->' ;
 sEndFragment   = '<!--EndFragment-->' ;
var  
 iBodyPosStart ,iBodyPosEnd ,
 iStartPos, iEndPos, iHeadLen,iUtf8Pos :Integer;
 ssOutput :TStringStream;
 sHeadStr,sUtf8Str :string;
 p :PChar;
begin
  // 把剪贴板源码转换为剪贴板格式 HTML Format
 Result := '' ;
 if psInput = '' then Exit;
 
  // ToDo: Check Utf8 Format : Utf8Encode(psInput)
  // 检查是否已经过 UTF-8 编码 , 防止重复编码
 iUtf8Pos := Pos( 'charset= utf-8">' ,LowerCase(psInput));
 if iUtf8Pos= 0 then
    sUtf8Str := Utf8Encode(psInput)
 else
    sUtf8Str := psInput; 
 
  { MSDN 中查找: HTML Clipboard Format
    内容是 UTF8 格式
    HeadStr              -> ClipHead
    DocHead              -> HTML First Row
    <html>               |
    <head>              |
    <title></title>     | -> HTMLHead
    <mete ....          |
    </head>             |
    <body class="g1"> |
    <!--StartFragment-->
    <pre>               |
    <div ..               | -> HTMLBody
    </pre>              |
    <!--EndFragment-->
    </body>            | -> HTMLEnd
    </html>             |
 }
  
  ssOutput := TStringStream.Create( '' );
 try
    sHeadStr := Format(sClipHead,[ 0 , 0 , 0 , 0 , 0 , 0 , 'about:blank' ]);  // 先留位置
    iHeadLen := Length(sHeadStr); 
    ssOutput.Write(sHeadStr[ 1 ],iHeadLen);
 
    ssOutput.Write(sDocHead[ 1 ],Length(sDocHead));
 
    // 确定 <body>...</body> 范围
    iBodyPosEnd := Pos( '</body>' ,LowerCase(sUtf8Str));
    if iBodyPosEnd =- 1 then iBodyPosEnd := Length(sUtf8Str);
    iBodyPosStart := Pos( '<body' ,LowerCase(sUtf8Str));
    Inc(iBodyPosStart, 4 );
    while (iBodyPosStart< iBodyPosEnd) and (sUtf8Str[iBodyPosStart]<> '>' ) do
      Inc(iBodyPosStart);                      
    Inc(iBodyPosStart);
 
    // 写源码头 <html>...<body>
    ssOutput.Write(sUtf8Str[ 1 ],iBodyPosStart);
    iStartPos := ssOutput.Position;
 
    // 写内容开始标识
    ssOutput.Write(sStartFragment,Length(sStartFragment));
 
    // 写源码内容  <body> ... </body> 之间数据
    //msOutput.Write((Pointer(Integer(@sUtf8Str[1]) + iBodyPosStart))^,
    //   iBodyPosEnd - iBodyPosStart -1 );
    ssOutput.Write(sUtf8Str[iBodyPosStart+ 1 ],
      iBodyPosEnd - iBodyPosStart - 1 );       
    iEndPos := ssOutput.Position ;
      
    // 写内容结束标识    
    ssOutput.Write(sEndFragment,Length(sEndFragment));
   
    // 写源码结尾 </body>...</html>
    //msOutput.Write((Pointer(Integer(@sUtf8Str[1]) + iBodyPosEnd -1)^),
    //   Length(sUtf8Str) - iBodyPosEnd+1);
    ssOutput.Write(sUtf8Str[iBodyPosEnd],
      Length(sUtf8Str) - iBodyPosEnd + 1 );   
 
    sHeadStr := Format(sClipHead,[iHeadLen,ssOutput.Size,iStartPos,iEndPos,
                              iStartPos,iEndPos, 'about:blank' ]);
    p := PChar(sHeadStr);
    CopyMemory(PChar(ssOutput.DataString),p,iHeadLen);
    Result := ssOutput.DataString;
 finally
    ssOutput.Free;
 end;  
end ;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值