用DELPHI、RxRichEdit控件实现类似QQ的表情输入方法

    技术2022-05-11  79

    在UDP即时通讯软件中实现类似于QQ的动画表情,在richEdit控件中插入gif动画表情。发送的时候将表情转为命令,接收之后,再将命令转换为相应的动画表情。需要引用一个QQ的DLL,文件在附件中。将此DLL导入到DELPHI中。

    源码及DLL 附件下载地址:http://www.j2soft.cnunit URichEdit;interfaceuses  Windows, Messages, SysUtils, Classes, Controls, StdCtrls, ActiveX, ComCtrls,  RxRichEd, OleServer, ImageOleLib_TLB, coconst, UConst, Dialogs;const  REO_CP_SELECTION = ULONG(-1);  REO_BELOWBASELINE = $00000002;  REO_RESIZABLE = $00000001;  REO_STATIC = $40000000;  EM_GETOLEINTERFACE = WM_USER + 60;  IID_IUnknown: TGUID = (D1: $00000000; D2: $0000; D3: $0000;     D4: ($C0, $00, $00, $00, $00, $00, $00, $46));  IID_IOleObject: TGUID = (D1: $00000112; D2: $0000; D3: $0000;     D4: ($C0, $00, $00, $00, $00, $00, $00, $46));type  _ReObject = record    cbStruct: DWORD; { Size of structure }    cp: ULONG; { Character position of Object }    clsid: TCLSID; { Class ID of Object }    pOleObj: IOleObject; { Ole Object interface }    pstg: IStorage; { Associated storage interface }    pOleSite: IOleClientSite; { Associated Client Site interface }    sizel: TSize; { Size of Object (may be 0,0) }    dvAspect: Longint; { Display aspect to use }    dwFlags: DWORD; { Object status flags }    dwUser: DWORD; { Dword for user憇 use }  end;  TReObject = _ReObject;  TCharRange = record {Copy From RichEdit.pas}    cpMin: Integer;    cpMax: Integer;  end;  TFormatRange = record    hdc: Integer;    hdcTarget: Integer;    rectRegion: TRect;    rectPage: TRect;    chrg: TCharRange;  end;  IRichEditOle = interface(System.IUnknown)    ['{00020d00-0000-0000-c000-000000000046}']    function GetClientSite(out ClientSite: IOleClientSite): HResult; stdcall;    function GetObjectCount: HResult; stdcall;    function GetLinkCount: HResult; stdcall;    function GetObject(iob: Longint; out ReObject: TReObject;         dwFlags: DWORD): HResult; stdcall;    function InsertObject(var ReObject: TReObject): HResult; stdcall;    function ConvertObject(iob: Longint; rclsidNew: TIID;         lpstrUserTypeNew: LPCSTR): HResult; stdcall;    function ActivateAs(rclsid: TIID; rclsidAs: TIID): HResult; stdcall;    function SetHostNames(lpstrContainerApp: LPCSTR;         lpstrContainerObj: LPCSTR): HResult; stdcall;    function SetLinkAvailable(iob: Longint; fAvailable: BOOL): HResult; stdcall;    function SetDvaspect(iob: Longint; dvAspect: DWORD): HResult; stdcall;    function HandsOffStorage(iob: Longint): HResult; stdcall;    function SaveCompleted(iob: Longint; const stg: IStorage): HResult; stdcall;    function InPlaceDeactivate: HResult; stdcall;    function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;    function GetClipboardData(var chrg: TCharRange; reco: DWORD;         out dataObj: IDataObject): HResult; stdcall;    function ImportDataObject(dataObj: IDataObject; cf: TClipFormat;         hMetaPict: HGLOBAL): HResult; stdcall;  end;  procedure InsertGif(re: TRxRichEdit; sFileName: string; dwUser: integer);  function GetGif (re: TRxRichEdit): TList;  function ConvertMsgToCmd (re: TRxRichEdit): string;  procedure ConvertMsgToFace (re: TRxRichEdit; strMsg: string);implementation//***************************************************//名称:InsertGif//功能:插入图片//输入:re:RichEdit控件;sFileName:要插入的文件名;//      dwUser:(标识,随机数,暂时用文件名【索引】代替)//输出://返回://***************************************************procedure InsertGif(re: TRxRichEdit; sFileName: string; dwUser: integer);type  tagSize = TSize;var  FRTF: IRichEditOle;  FLockBytes: ILockBytes;  FStorage: ISTORAGE;  FClientSite: IOLECLIENTSITE;  m_lpObject: IOleObject;  m_lpAnimator: TGifAnimator;  i_GifAnimator: IGifAnimator;  reobject: TReObject;  clsid: TGuid;  sizel: tagSize;  Rect: TRect;begin  try    if CreateILockBytesOnHGlobal(0, True, FLockBytes) <> S_OK then    begin      //showmessage('Error to create Global Heap');      exit;    end;  //????????????    if StgCreateDocfileOnILockBytes(FLockBytes, STGM_SHARE_EXCLUSIVE or      STGM_CREATE or STGM_READWRITE, 0, FStorage) <> S_OK then    begin      //Showmessage('Error to create storage');      exit;    end;  //??RichEdit???    Sendmessage(re.handle, EM_GETOLEINTERFACE, 0, LongInt(@FRTF));    if FRTF.GetClientSite(FClientSite) <> S_OK then    begin      //ShowMessage('Error to get ClentSite');      Exit;    end;        CoInitializeEx(nil, COINIT_APARTMENTTHREADED);    m_lpAnimator := TGifAnimator.Create(re);    i_GifAnimator := m_lpAnimator.ControlInterface;    i_GifAnimator.LoadFromFile(sFileName);    i_GifAnimator.QueryInterface(IID_IOleObject, m_lpObject);    OleSetContainedObject(m_lpObject, True);    FillChar(ReObject, SizeOf(ReObject), 0);    ReObject.cbStruct := SizeOf(ReObject);    m_lpObject.GetUserClassID(clsid);    ReObject.clsid := clsid;    reobject.cp := REO_CP_SELECTION;  //content, but not static    reobject.dvaspect := DVASPECT_CONTENT;  //goes in the same line of text line    reobject.dwFlags := REO_BELOWBASELINE; //REO_RESIZABLE |    reobject.dwUser := 0;  //the very object    reobject.poleobj := m_lpObject;  //client site contain the object    reobject.polesite := FClientSite;  //the storage    reobject.pstg := FStorage;    sizel.cx := 0;    sizel.cy := 0;    reobject.sizel := sizel;  //Sel all text    re.SelText := '';    re.SelLength := 0;    re.SelStart := re.SelStart;    reobject.dwUser := dwUser;  //Insert after the line of text    FRTF.InsertObject(reobject);    SendMessage(re.Handle, EM_SCROLLCARET, 0, 0);  //VARIANT_BOOL ret;  //do frame changing    m_lpAnimator.TriggerFrameChange();  //show it    m_lpObject.DoVerb(OLEIVERB_UIACTIVATE, nil, FClientSite, 0, re.Handle, Rect); // m_lpObject.DoVerb(    m_lpObject.DoVerb(OLEIVERB_SHOW, nil, FClientSite, 0, re.Handle, Rect);  //redraw the window to show animation    RedrawWindow(re.Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_FRAME or         RDW_ERASENOW or RDW_ALLCHILDREN);  finally    FRTF := nil;    FClientSite := nil;    FStorage := nil;  end;end;//***************************************************//名称:GetGif//功能:分析控件内容,取得控件中的图片对象//输入:re:RichEdit控件;//输出://返回:取得的对象列表(图片索引、图片位置)//***************************************************function GetGif (re: TRxRichEdit): TList;type  tagSize = TSize;var  i: integer;  FRTF: IRichEditOle;  ReObject: TReObject;  lstGif: TList;  slstRow: TStringList;begin  lstGif := TList.Create;  Sendmessage(re.handle, EM_GETOLEINTERFACE, 0, LongInt(@FRTF));  for i := 0 to FRTF.GetObjectCount - 1 do  begin    slstRow := TStringList.Create;    FillChar(ReObject, SizeOf(ReObject), 0);    ReObject.cbStruct := SizeOf(ReObject);    FRTF.GetObject (Longint (i), ReObject, REO_BELOWBASELINE);    slstRow.Add (IntToStr (ReObject.dwUser));    slstRow.Add (IntToStr (ReObject.cp));    lstGif.Add (slstRow);  end;  Result := lstGif;end;//***************************************************//名称:ConvertMsgToCmd//功能:分析控件内容,将表情替换成相应的命令//输入:re:RichEdit控件;//输出://返回:转换之后的消息内容//***************************************************function ConvertMsgToCmd (re: TRxRichEdit): string;var  i: integer;  lstGif: TList;  strMsg: WideString;  slstRow, slstMsg: TStringList;begin  //分解消息文本内容,将所有内容分隔之后放到列表中  slstMsg := TStringList.Create;  strMsg := re.Text;  for i := 1 to Length (strMsg) do  begin    slstMsg.Add (strMsg[i]);  end;  //取得表情,将表情替换成命令  lstGif := GetGif (re);  for i := lstGif.Count - 1 downto 0 do  begin    slstRow := TStringList (lstGif.Items[i]);    slstMsg.Insert (StrToInt (slstRow.Strings[1]),         m_arrFace[StrToInt (slstRow.Strings[0]), 1]);    slstRow.Free;  end;  lstGif.Free;  strMsg := StringReplace (slstMsg.Text, #13#10, '', [rfReplaceAll]);  slstMsg.Free;  Result := strMsg;end;//***************************************************//名称:ConvertMsgToFace//功能:分析消息内容,将命令换成相应的表情//输入:re:RichEdit控件;strMsg:消息内容;//输出://返回://***************************************************procedure ConvertMsgToFace (re: TRxRichEdit; strMsg: string);var  i, nFind: integer;  strPath: string;  strMessage: WideString;begin  if StrPos (PChar (strMsg), '/') = nil then  begin    exit;  end;  strMessage := strMsg;  strPath := ExtractFilePath (ParamStr (0)) + SYSSET_CHAT_FACEPATH;  for i := 0 to Length (m_arrFace) - 1 do  begin    nFind := Pos (PChar (m_arrFace[i, 1]), strMessage);    if nFind = 0 then      continue    else begin      re.SelStart := nFind - 2;      re.SelLength := Length (m_arrFace[i, 1]);      InsertGif (re, strPath + m_arrFace[i, 0], i);    end;  end;end;end. 


    最新回复(0)