| 導購 | 订阅 | 在线投稿
分享
 
 
 

CRichEditCtrl實現MSN/QQ動畫表情

來源:互聯網  2008-06-01 02:11:18  評論

首先對標題說明一下,在MSN中,聊天的窗口可能是一個自定義的類。大家用Spy ++可以看看。對與自定義窗口,可以使用CreateWindow, SetWindowLong或者是SubclassWindow實現,不過這不是我現在討論的話題。

好, 先看看效果再說:

CRichEditCtrl實現MSN/QQ動畫表情

關于這個的實現。我們首先應該明了,我們必須實現一個OLE對象。而且這個對象能夠播放GIF.對于播放GIF,代碼已經很多了。

有了這個就完了麽?當然不是。你還有寫一個OLE/COM對象。實現IOleObject等。你是用ATL還是MFC呢?我什麽也沒有用。在這個目錄下%PRogram file%\tencent\QQ\,你可以看到一個ImageOle.dll,她就是你日夜思念的人!

好吧,讓我們來看看他的真面目。怎麽看?X Ray? 當然不是——OLE/COM Viewer.Click on 「All Objects」,View TypeLib... 打開那個文件,你可以看到:

[

uuid(0C1CF2DF-05A3-4FEF-8CD4-F5CFC4355A16),

helpstring("IGifAnimator Interface"),

dual,

nonextensible

]

dispinterface IGifAnimator {

properties:

methods:

[id(0x00000001), helpstring("method LoadFromFile")]

void LoadFromFile([in] BSTR FileName);

[id(0x00000002), helpstring("method TriggerFrameChange")]

VARIANT_BOOL TriggerFrameChange();

[id(0x00000003), helpstring("method GetFilePath")]

BSTR GetFilePath();

[id(0x00000004), helpstring("method ShowText")]

void ShowText([in] BSTR Text);

};

這個接口就是我們要的。你可以用ActiveX Control Test Container測試一下。還挺管用的。

以下給出代碼:

首先我們導入ImageOle.dll

#import "D:\\Program files\\tencent\\qq\\ImageOle.dll" named_guidsnamed_guids 表示讓編譯器爲我把對應庫的GUID和聲明對應起來。我們就可以用CLSID_GifAnimator引用對應的接口了。不用那一長串的東西。然後它就會爲我們生成兩個文件。

CRichEditCtrl實現MSN/QQ動畫表情
更多內容請看MSN圖像 MSN專題 QQ表情專題,或

ImageOle.tlh

1// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (9de7951a).

2//

3// d:\myproject\msger\debug\ImageOle.tlh

4//

5// C++ source equivalent of Win32 type library D:\\Program files\\tencent\\qq\\ImageOle.dll

6// compiler-generated file created 10/25/04 at 22:00:58 - DO NOT EDIT!

7#pragma once

8#pragma pack(push, 8)

9#include

10

11namespace ImageOleLib {

12

13//

14// Forward references and typedefs

15//

16

17strUCt /* coclass */ GifAnimator;

18struct __declspec(uuid("0c1cf2df-05a3-4fef-8cd4-f5cfc4355a16"))

19/* dual interface */ IGifAnimator;

20

21//

22// Smart pointer typedef declarations

23//

24

25_COM_SMARTPTR_TYPEDEF(IGifAnimator, __uuidof(IGifAnimator));

26

27//

28// Type library items

29//

30

31struct __declspec(uuid("06ada938-0fb0-4bc0-b19b-0a38ab17f182"))

32GifAnimator;

33 // [ default ] interface IGifAnimator

34

35struct __declspec(uuid("0c1cf2df-05a3-4fef-8cd4-f5cfc4355a16"))

36IGifAnimator : IDispatch

37{

38 //

39 // Wrapper methods for error-handling

40 //

41

42 HRESULT LoadFromFile (

43 _bstr_t FileName );

44 VARIANT_BOOL TriggerFrameChange ( );

45 _bstr_t GetFilePath ( );

46 HRESULT ShowText (

47 _bstr_t Text );

48

49 //

50 // Raw methods provided by interface

51 //

52

53 virtual HRESULT __stdcall raw_LoadFromFile (

54 BSTR FileName ) = 0;

55 virtual HRESULT __stdcall raw_TriggerFrameChange (

56 VARIANT_BOOL * pbChanged ) = 0;

57 virtual HRESULT __stdcall raw_GetFilePath (

58 BSTR * pFilePath ) = 0;

59 virtual HRESULT __stdcall raw_ShowText (

60 BSTR Text ) = 0;

61};

62

63//

64// Named GUID constants initializations

65//

66

67extern "C" const GUID __declspec(selectany) LIBID_ImageOleLib =

68 {0x710993a2,0x4f87,0x41d7,{0xb6,0xfe,0xf5,0xa2,0x03,0x68,0x46,0x5f}};

69extern "C" const GUID __declspec(selectany) CLSID_GifAnimator =

70 {0x06ada938,0x0fb0,0x4bc0,{0xb1,0x9b,0x0a,0x38,0xab,0x17,0xf1,0x82}};

71extern "C" const GUID __declspec(selectany) IID_IGifAnimator =

72 {0x0c1cf2df,0x05a3,0x4fef,{0x8c,0xd4,0xf5,0xcf,0xc4,0x35,0x5a,0x16}};

73

74//

75// Wrapper method implementations

76//

77#include "d:\myproject\msger\debug\ImageOle.tli"

78

79} // namespace ImageOleLib

80#pragma pack(pop)

CRichEditCtrl實現MSN/QQ動畫表情
更多內容請看MSN圖像 MSN專題 QQ表情專題,或

ImageOle.tli

1// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (9de7951a).

2//

3// d:\myproject\msger\debug\ImageOle.tli

4//

5// Wrapper implementations for Win32 type library D:\\Program files\\tencent\\qq\\ImageOle.dll

6// compiler-generated file created 10/25/04 at 22:00:58 - DO NOT EDIT!

7#pragma once

8

9//

10// interface IGifAnimator wrapper method implementations

11//

12

13inline HRESULT IGifAnimator::LoadFromFile ( _bstr_t FileName ) {

14 HRESULT _hr = raw_LoadFromFile(FileName);

15 if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));

16 return _hr;

17}

18

19inline VARIANT_BOOL IGifAnimator::TriggerFrameChange ( ) {

20 VARIANT_BOOL _result;

21 HRESULT _hr = raw_TriggerFrameChange(&_result);

22 if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));

23 return _result;

24}

25

26inline _bstr_t IGifAnimator::GetFilePath ( ) {

27 BSTR _result;

28 HRESULT _hr = raw_GetFilePath(&_result);

29 if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));

30 return _bstr_t(_result, false);

31}

32

33inline HRESULT IGifAnimator::ShowText ( _bstr_t Text ) {

34 HRESULT _hr = raw_ShowText(Text);

35 if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));

36 return _hr;

37}

有了這些,你使用接口和函數就很方便了。

然後就這樣:

WINOLEAPI CoInitializeEx(LPVOID pvReserved, DWord dwCoInit)

爲什麽要這樣呢?因爲我們使用這個函數。那有必要這樣麽?在MSDN是說要 #define _DCOM_ 就行了。可惜我沒有成功。就只好這樣了。

接著就是實現代碼了。現在看應該沒有很大的問題。假如還是很難明白。那麽我你得好好研究CRichEditCtrl和OLE了。聽說Inside OLE和Inside COM很好。我沒有弄到。就看了《COM+編程指南》和潘愛民的《COM原理和應用》,不錯!還有一個好東西。就是 ActiveX Control Test Container 的源代碼。

CRichEditCtrl實現MSN/QQ動畫表情
更多內容請看MSN圖像 MSN專題 QQ表情專題,或

最後該出場的就是實現代碼了。

1 LPLOCKBYTES lpLockBytes = NULL;

2 SCODE sc;

3 HRESULT hr;

4 //print to RichEdit' s IClientSite

5 LPOLECLIENTSITE m_lpClientSite;

6 //A smart point to IAnimator

7 IGifAnimatorPtr m_lpAnimator;

8 //ptr 2 storage

9 LPSTORAGE m_lpStorage;

10 //the object 2 b insert 2

11 LPOLEOBJECT m_lpObject;

12

13 //Create lockbytes

14 sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);

15 if (sc != S_OK)

16 AfxThrowOleException(sc);

17 ASSERT(lpLockBytes != NULL);

18

19 //use lockbytes to create storage

20 sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,

21 STGM_SHARE_EXCLUSIVESTGM_CREATESTGM_READWRITE, 0, &m_lpStorage);

22 if (sc != S_OK)

23 {

24 VERIFY(lpLockBytes->Release() == 0);

25 lpLockBytes = NULL;

26 AfxThrowOleException(sc);

27 }

28 ASSERT(m_lpStorage != NULL);

29

30 //get the ClientSite of the very RichEditCtrl

31 GetIRichEditOle()->GetClientSite(&m_lpClientSite);

32 ASSERT(m_lpClientSite != NULL);

33

34 try

35 {

36 //Initlize COM interface

37 hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );

38 if( FAILED(hr) )

39 _com_issue_error(hr);

40

41 //Get GifAnimator object

42 //here, I used a smart point, so I do not need to free it

43 hr = m_lpAnimator.CreateInstance(CLSID_GifAnimator);

44 if( FAILED(hr) )

45 _com_issue_error(hr);

46 //COM Operation need BSTR, so get a BSTR

47 BSTR path = strPicPath.AllocSysString();

48

49 //Load the gif

50 hr = m_lpAnimator->LoadFromFile(path);

51 if( FAILED(hr) )

52 _com_issue_error(hr);

53

54 TRACE0( m_lpAnimator->GetFilePath() );

55

56 //get the IOleObject

57 hr = m_lpAnimator.QueryInterface(IID_IOleObject, (void**)&m_lpObject);

58 if( FAILED(hr) )

59 _com_issue_error(hr);

60

61 //Set it 2 b inserted

62 OleSetContainedObject(m_lpObject, TRUE);

63

64 //2 insert in 2 richedit, you need a struct of REOBJECT

65 REOBJECT reobject;

66 ZeroMemory(&reobject, sizeof(REOBJECT));

67

68 reobject.cbStruct = sizeof(REOBJECT);

69 CLSID clsid;

70 sc = m_lpObject->GetUserClassID(&clsid);

71 if (sc != S_OK)

72 AfxThrowOleException(sc);

73 //set clsid

74 reobject.clsid = clsid;

75 //can be selected

76 reobject.cp = REO_CP_SELECTION;

77 //content, but not static

78 reobject.dvaspect = DVASPECT_CONTENT;

79 //goes in the same line of text line

80 reobject.dwFlags = REO_BELOWBASELINE; //REO_RESIZABLE

81 reobject.dwUser = 0;

82 //the very object

83 reobject.poleobj = m_lpObject;

84 //client site contain the object

85 reobject.polesite = m_lpClientSite;

86 //the storage

87 reobject.pstg = m_lpStorage;

88

89 SIZEL sizel;

90 sizel.cx = sizel.cy = 0;

91 reobject.sizel = sizel;

92 HWND hWndRT = this->m_hWnd;

93 //Sel all text

94// ::SendMessage(hWndRT, EM_SETSEL, 0, -1);

95// DWORD dwStart, dwEnd;

96// ::SendMessage(hWndRT, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);

97// ::SendMessage(hWndRT, EM_SETSEL, dwEnd+1, dwEnd+1);

98 //Insert after the line of text

99 GetIRichEditOle()->InsertObject(&reobject);

100 ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);

101 VARIANT_BOOL ret;

102 //do frame changing

103 ret = m_lpAnimator->TriggerFrameChange();

104 //show it

105 m_lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_lpClientSite, 0, m_hWnd, NULL);

106 m_lpObject->DoVerb(OLEIVERB_SHOW, NULL, m_lpClientSite, 0, m_hWnd, NULL);

107

108 //redraw the window to show animation

109 RedrawWindow();

110

111 if (m_lpClientSite)

112 {

113 m_lpClientSite->Release();

114 m_lpClientSite = NULL;

115 }

116 if (m_lpObject)

117 {

118 m_lpObject->Release();

119 m_lpObject = NULL;

120 }

121 if (m_lpStorage)

122 {

123 m_lpStorage->Release();

124 m_lpStorage = NULL;

125 }

126

127 SysFreeString(path);

128 }

129 catch( _com_error e )

130 {

131 AfxMessageBox(e.ErrorMessage());

132 ::CoUninitialize();

133 }

CRichEditCtrl實現MSN/QQ動畫表情
更多內容請看MSN圖像 MSN專題 QQ表情專題,或

附:Delphi版的實現

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls, ActiveX, ComCtrls, RxRichEd, ImageOleLib_TLB;

//RxRichEd單元是Rxlib下的RxRichEdit,一套增強功能的RichEdit

//ImageOleLib_TLB是從qq的ImageOle.dll引入的類型庫

const

IID_IOleObject: TGUID = (

D1: $00000112; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00,

$46));

EM_GETOLEINTERFACE= WM_USER + 60;

type

TForm1 = class(TForm)

Button1: TButton;

Editor: TRxRichEdit;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);

var

FRTF: IRichEditOle;

FLockBytes: ILockBytes;

FStorage: ISTORAGE;

FClientSite: IOLECLIENTSITE;

m_lpObject: IOleObject;

m_lpAnimator: TGifAnimator;

i_GifAnimator: IGifAnimator;

reobject: TReObject;

clsid: TGuid;

sizel: tagSize;

dwStart, dwEnd: DWORD;

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(Editor.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(Self);

i_GifAnimator := m_lpAnimator.ControlInterface;

i_GifAnimator.LoadFromFile('c:\ti.gif');

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

SendMessage(Editor.Handle, EM_SETSEL, 0, -1);

SendMessage(Editor.Handle, EM_GETSEL, dwStart, dwEnd);

SendMessage(Editor.Handle, EM_SETSEL, dwEnd + 1, dwEnd + 1);

//Insert after the line of text

FRTF.InsertObject(reobject);

SendMessage(Editor.Handle, EM_SCROLLCARET, 0, 0);

//VARIANT_BOOL ret;

//do frame changing

m_lpAnimator.TriggerFrameChange();

//show it

m_lpObject.DoVerb(OLEIVERB_UIACTIVATE, Nil, FClientSite, 0, Editor.Handle,Rect);

// m_lpObject.DoVerb(

m_lpObject.DoVerb(OLEIVERB_SHOW, Nil, FClientSite, 0, Editor.Handle, Rect);

//redraw the window to show animation

redrawwindow(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;

end

CRichEditCtrl實現MSN/QQ動畫表情
更多內容請看MSN圖像 MSN專題 QQ表情專題,或

  首先對標題說明一下,在MSN中,聊天的窗口可能是一個自定義的類。大家用Spy ++可以看看。對與自定義窗口,可以使用CreateWindow, SetWindowLong或者是SubclassWindow實現,不過這不是我現在討論的話題。   好, 先看看效果再說: [url=/bbs/detail_1785463.html][img]http://image.wangchao.net.cn/it/1323423083958.jpg[/img][/url]   關于這個的實現。我們首先應該明了,我們必須實現一個OLE對象。而且這個對象能夠播放GIF.對于播放GIF,代碼已經很多了。   有了這個就完了麽?當然不是。你還有寫一個OLE/COM對象。實現IOleObject等。你是用ATL還是MFC呢?我什麽也沒有用。在這個目錄下%PRogram file%\tencent\QQ\,你可以看到一個ImageOle.dll,她就是你日夜思念的人!   好吧,讓我們來看看他的真面目。怎麽看?X Ray? 當然不是——OLE/COM Viewer.Click on 「All Objects」,View TypeLib... 打開那個文件,你可以看到: [ uuid(0C1CF2DF-05A3-4FEF-8CD4-F5CFC4355A16), helpstring("IGifAnimator Interface"), dual, nonextensible ] dispinterface IGifAnimator { properties: methods: [id(0x00000001), helpstring("method LoadFromFile")] void LoadFromFile([in] BSTR FileName); [id(0x00000002), helpstring("method TriggerFrameChange")] VARIANT_BOOL TriggerFrameChange(); [id(0x00000003), helpstring("method GetFilePath")] BSTR GetFilePath(); [id(0x00000004), helpstring("method ShowText")] void ShowText([in] BSTR Text); };   這個接口就是我們要的。你可以用ActiveX Control Test Container測試一下。還挺管用的。   以下給出代碼:   首先我們導入ImageOle.dll #import "D:\\Program files\\tencent\\qq\\ImageOle.dll" named_guids  named_guids 表示讓編譯器爲我把對應庫的GUID和聲明對應起來。我們就可以用CLSID_GifAnimator引用對應的接口了。不用那一長串的東西。然後它就會爲我們生成兩個文件。 [url=/bbs/detail_1785463.html][img]http://image.wangchao.net.cn/it/1323423099307.gif[/img][/url] 更多內容請看MSN圖像 MSN專題 QQ表情專題,或 ImageOle.tlh 1// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (9de7951a). 2// 3// d:\myproject\msger\debug\ImageOle.tlh 4// 5// C++ source equivalent of Win32 type library D:\\Program files\\tencent\\qq\\ImageOle.dll 6// compiler-generated file created 10/25/04 at 22:00:58 - DO NOT EDIT! 7#pragma once 8#pragma pack(push, 8) 9#include 10 11namespace ImageOleLib { 12 13// 14// Forward references and typedefs 15// 16 17strUCt /* coclass */ GifAnimator; 18struct __declspec(uuid("0c1cf2df-05a3-4fef-8cd4-f5cfc4355a16")) 19/* dual interface */ IGifAnimator; 20 21// 22// Smart pointer typedef declarations 23// 24 25_COM_SMARTPTR_TYPEDEF(IGifAnimator, __uuidof(IGifAnimator)); 26 27// 28// Type library items 29// 30 31struct __declspec(uuid("06ada938-0fb0-4bc0-b19b-0a38ab17f182")) 32GifAnimator; 33 // [ default ] interface IGifAnimator 34 35struct __declspec(uuid("0c1cf2df-05a3-4fef-8cd4-f5cfc4355a16")) 36IGifAnimator : IDispatch 37{ 38 // 39 // Wrapper methods for error-handling 40 // 41 42 HRESULT LoadFromFile ( 43 _bstr_t FileName ); 44 VARIANT_BOOL TriggerFrameChange ( ); 45 _bstr_t GetFilePath ( ); 46 HRESULT ShowText ( 47 _bstr_t Text ); 48 49 // 50 // Raw methods provided by interface 51 // 52 53 virtual HRESULT __stdcall raw_LoadFromFile ( 54 BSTR FileName ) = 0; 55 virtual HRESULT __stdcall raw_TriggerFrameChange ( 56 VARIANT_BOOL * pbChanged ) = 0; 57 virtual HRESULT __stdcall raw_GetFilePath ( 58 BSTR * pFilePath ) = 0; 59 virtual HRESULT __stdcall raw_ShowText ( 60 BSTR Text ) = 0; 61}; 62 63// 64// Named GUID constants initializations 65// 66 67extern "C" const GUID __declspec(selectany) LIBID_ImageOleLib = 68 {0x710993a2,0x4f87,0x41d7,{0xb6,0xfe,0xf5,0xa2,0x03,0x68,0x46,0x5f}}; 69extern "C" const GUID __declspec(selectany) CLSID_GifAnimator = 70 {0x06ada938,0x0fb0,0x4bc0,{0xb1,0x9b,0x0a,0x38,0xab,0x17,0xf1,0x82}}; 71extern "C" const GUID __declspec(selectany) IID_IGifAnimator = 72 {0x0c1cf2df,0x05a3,0x4fef,{0x8c,0xd4,0xf5,0xcf,0xc4,0x35,0x5a,0x16}}; 73 74// 75// Wrapper method implementations 76// 77#include "d:\myproject\msger\debug\ImageOle.tli" 78 79} // namespace ImageOleLib 80#pragma pack(pop) [url=/bbs/detail_1785463.html][img]http://image.wangchao.net.cn/it/1323423099329.gif[/img][/url] 更多內容請看MSN圖像 MSN專題 QQ表情專題,或 ImageOle.tli 1// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (9de7951a). 2// 3// d:\myproject\msger\debug\ImageOle.tli 4// 5// Wrapper implementations for Win32 type library D:\\Program files\\tencent\\qq\\ImageOle.dll 6// compiler-generated file created 10/25/04 at 22:00:58 - DO NOT EDIT! 7#pragma once 8 9// 10// interface IGifAnimator wrapper method implementations 11// 12 13inline HRESULT IGifAnimator::LoadFromFile ( _bstr_t FileName ) { 14 HRESULT _hr = raw_LoadFromFile(FileName); 15 if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); 16 return _hr; 17} 18 19inline VARIANT_BOOL IGifAnimator::TriggerFrameChange ( ) { 20 VARIANT_BOOL _result; 21 HRESULT _hr = raw_TriggerFrameChange(&_result); 22 if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); 23 return _result; 24} 25 26inline _bstr_t IGifAnimator::GetFilePath ( ) { 27 BSTR _result; 28 HRESULT _hr = raw_GetFilePath(&_result); 29 if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); 30 return _bstr_t(_result, false); 31} 32 33inline HRESULT IGifAnimator::ShowText ( _bstr_t Text ) { 34 HRESULT _hr = raw_ShowText(Text); 35 if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); 36 return _hr; 37}   有了這些,你使用接口和函數就很方便了。   然後就這樣:   WINOLEAPI CoInitializeEx(LPVOID pvReserved, DWord dwCoInit)   爲什麽要這樣呢?因爲我們使用這個函數。那有必要這樣麽?在MSDN是說要 #define _DCOM_ 就行了。可惜我沒有成功。就只好這樣了。   接著就是實現代碼了。現在看應該沒有很大的問題。假如還是很難明白。那麽我你得好好研究CRichEditCtrl和OLE了。聽說Inside OLE和Inside COM很好。我沒有弄到。就看了《COM+編程指南》和潘愛民的《COM原理和應用》,不錯!還有一個好東西。就是 ActiveX Control Test Container 的源代碼。 [url=/bbs/detail_1785463.html][img]http://image.wangchao.net.cn/it/1323423099346.gif[/img][/url] 更多內容請看MSN圖像 MSN專題 QQ表情專題,或   最後該出場的就是實現代碼了。 1 LPLOCKBYTES lpLockBytes = NULL; 2 SCODE sc; 3 HRESULT hr; 4 //print to RichEdit' s IClientSite 5 LPOLECLIENTSITE m_lpClientSite; 6 //A smart point to IAnimator 7 IGifAnimatorPtr m_lpAnimator; 8 //ptr 2 storage 9 LPSTORAGE m_lpStorage; 10 //the object 2 b insert 2 11 LPOLEOBJECT m_lpObject; 12 13 //Create lockbytes 14 sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); 15 if (sc != S_OK) 16 AfxThrowOleException(sc); 17 ASSERT(lpLockBytes != NULL); 18 19 //use lockbytes to create storage 20 sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, 21 STGM_SHARE_EXCLUSIVESTGM_CREATESTGM_READWRITE, 0, &m_lpStorage); 22 if (sc != S_OK) 23 { 24 VERIFY(lpLockBytes->Release() == 0); 25 lpLockBytes = NULL; 26 AfxThrowOleException(sc); 27 } 28 ASSERT(m_lpStorage != NULL); 29 30 //get the ClientSite of the very RichEditCtrl 31 GetIRichEditOle()->GetClientSite(&m_lpClientSite); 32 ASSERT(m_lpClientSite != NULL); 33 34 try 35 { 36 //Initlize COM interface 37 hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); 38 if( FAILED(hr) ) 39 _com_issue_error(hr); 40 41 //Get GifAnimator object 42 //here, I used a smart point, so I do not need to free it 43 hr = m_lpAnimator.CreateInstance(CLSID_GifAnimator); 44 if( FAILED(hr) ) 45 _com_issue_error(hr); 46 //COM Operation need BSTR, so get a BSTR 47 BSTR path = strPicPath.AllocSysString(); 48 49 //Load the gif 50 hr = m_lpAnimator->LoadFromFile(path); 51 if( FAILED(hr) ) 52 _com_issue_error(hr); 53 54 TRACE0( m_lpAnimator->GetFilePath() ); 55 56 //get the IOleObject 57 hr = m_lpAnimator.QueryInterface(IID_IOleObject, (void**)&m_lpObject); 58 if( FAILED(hr) ) 59 _com_issue_error(hr); 60 61 //Set it 2 b inserted 62 OleSetContainedObject(m_lpObject, TRUE); 63 64 //2 insert in 2 richedit, you need a struct of REOBJECT 65 REOBJECT reobject; 66 ZeroMemory(&reobject, sizeof(REOBJECT)); 67 68 reobject.cbStruct = sizeof(REOBJECT); 69 CLSID clsid; 70 sc = m_lpObject->GetUserClassID(&clsid); 71 if (sc != S_OK) 72 AfxThrowOleException(sc); 73 //set clsid 74 reobject.clsid = clsid; 75 //can be selected 76 reobject.cp = REO_CP_SELECTION; 77 //content, but not static 78 reobject.dvaspect = DVASPECT_CONTENT; 79 //goes in the same line of text line 80 reobject.dwFlags = REO_BELOWBASELINE; //REO_RESIZABLE 81 reobject.dwUser = 0; 82 //the very object 83 reobject.poleobj = m_lpObject; 84 //client site contain the object 85 reobject.polesite = m_lpClientSite; 86 //the storage 87 reobject.pstg = m_lpStorage; 88 89 SIZEL sizel; 90 sizel.cx = sizel.cy = 0; 91 reobject.sizel = sizel; 92 HWND hWndRT = this->m_hWnd; 93 //Sel all text 94// ::SendMessage(hWndRT, EM_SETSEL, 0, -1); 95// DWORD dwStart, dwEnd; 96// ::SendMessage(hWndRT, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); 97// ::SendMessage(hWndRT, EM_SETSEL, dwEnd+1, dwEnd+1); 98 //Insert after the line of text 99 GetIRichEditOle()->InsertObject(&reobject); 100 ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0); 101 VARIANT_BOOL ret; 102 //do frame changing 103 ret = m_lpAnimator->TriggerFrameChange(); 104 //show it 105 m_lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_lpClientSite, 0, m_hWnd, NULL); 106 m_lpObject->DoVerb(OLEIVERB_SHOW, NULL, m_lpClientSite, 0, m_hWnd, NULL); 107 108 //redraw the window to show animation 109 RedrawWindow(); 110 111 if (m_lpClientSite) 112 { 113 m_lpClientSite->Release(); 114 m_lpClientSite = NULL; 115 } 116 if (m_lpObject) 117 { 118 m_lpObject->Release(); 119 m_lpObject = NULL; 120 } 121 if (m_lpStorage) 122 { 123 m_lpStorage->Release(); 124 m_lpStorage = NULL; 125 } 126 127 SysFreeString(path); 128 } 129 catch( _com_error e ) 130 { 131 AfxMessageBox(e.ErrorMessage()); 132 ::CoUninitialize(); 133 } [url=/bbs/detail_1785463.html][img]http://image.wangchao.net.cn/it/1323423099362.gif[/img][/url] 更多內容請看MSN圖像 MSN專題 QQ表情專題,或 附:Delphi版的實現 unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ActiveX, ComCtrls, RxRichEd, ImageOleLib_TLB; //RxRichEd單元是Rxlib下的RxRichEdit,一套增強功能的RichEdit //ImageOleLib_TLB是從qq的ImageOle.dll引入的類型庫 const IID_IOleObject: TGUID = ( D1: $00000112; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00, $46)); EM_GETOLEINTERFACE= WM_USER + 60; type TForm1 = class(TForm) Button1: TButton; Editor: TRxRichEdit; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); var FRTF: IRichEditOle; FLockBytes: ILockBytes; FStorage: ISTORAGE; FClientSite: IOLECLIENTSITE; m_lpObject: IOleObject; m_lpAnimator: TGifAnimator; i_GifAnimator: IGifAnimator; reobject: TReObject; clsid: TGuid; sizel: tagSize; dwStart, dwEnd: DWORD; 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(Editor.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(Self); i_GifAnimator := m_lpAnimator.ControlInterface; i_GifAnimator.LoadFromFile('c:\ti.gif'); 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 SendMessage(Editor.Handle, EM_SETSEL, 0, -1); SendMessage(Editor.Handle, EM_GETSEL, dwStart, dwEnd); SendMessage(Editor.Handle, EM_SETSEL, dwEnd + 1, dwEnd + 1); //Insert after the line of text FRTF.InsertObject(reobject); SendMessage(Editor.Handle, EM_SCROLLCARET, 0, 0); //VARIANT_BOOL ret; //do frame changing m_lpAnimator.TriggerFrameChange(); //show it m_lpObject.DoVerb(OLEIVERB_UIACTIVATE, Nil, FClientSite, 0, Editor.Handle,Rect); // m_lpObject.DoVerb( m_lpObject.DoVerb(OLEIVERB_SHOW, Nil, FClientSite, 0, Editor.Handle, Rect); //redraw the window to show animation redrawwindow(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; end [url=/bbs/detail_1785463.html][img]http://image.wangchao.net.cn/it/1323423099381.gif[/img][/url] 更多內容請看MSN圖像 MSN專題 QQ表情專題,或
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有