要作一個相似QQ表情的東西,用BCB6.0來作,原本這個工具也不是熟悉,用得多仍是VC吧,難! html
上網查了一下,由於要播放GIF文件,那個在CSDN說的幾乎都是說用QQ的ImageOle來作,而後就是一大堆的連接,說哪里哪里有的,怎樣引用法 程序員
可是版權啊 服務器
並且全都是05年的帖子,奇怪了,難道是百度的錯,仍是如今沒有人作這個了 框架
無耐,繼續百度 google, ide
找到了一位哥們作的 函數
相似 MSN 信息發送框的製做(上)
http://www.vckbase.com/document/viewdoc/?id=1087 工具
惋惜啊,不能顯示GIF 並且那個表情的選擇面板也不太對勁,都是用Button來作的,圖片多了那不是慢得要死,這種方法不可取吧 oop
決定學習如何作一個ATL的com組件,本身實現一下這個組件吧 學習
這時又找到了這篇文章http://blog.csdn.net/wheatfield/article/details/5833532 測試
這篇文章說了不少關於ATL這些相關的內容知識
好比如何插入OLE對象
TCHAR Filter[]=_T("JGP文件(*.jpg)|*.jpg;*.jpeg|GIF文件(*.gif)|*.gif|BMP文件(*.bmp)|*.bmp|全部文件(*.*)|*.*||"); CFileDialog dlgOpen(TRUE,0,0,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,(LPCTSTR)Filter,NULL); if(dlgOpen.DoModal()==IDOK) { IRichEditOle* lpRichEditOle = m_RichEdit.GetIRichEditOle(); //m_RichEdit爲您的RichEdit對象 IStorage* lpStorage = NULL;//存儲接口 IOleObject* lpOleObject = NULL;//OLE對象 LPLOCKBYTES lpLockBytes = NULL;//LOCKBYTE IOleClientSite* lpOleClientSite = NULL; CComPtr<IMaiYuanOleImage> IPic; CLSID clsid; REOBJECT reobject; HRESULT hr; if(lpRichEditOle == NULL) return; //建立IMaiYuanOleImage對象並獲取接口 hr = ::CoCreateInstance(CLSID_MYOleImage,NULL,CLSCTX_INPROC,IID_IMaiYuanOleImage,(LPVOID*)&IPic); if( IPic == NULL ) { return; } BOOL bRet = TRUE; try{ hr = IPic->QueryInterface(IID_IOleObject, (void**)&lpOleObject);//得到數據對象接口 if( hr != S_OK ) AfxThrowOleException(hr); hr = lpOleObject->GetUserClassID(&clsid); if ( hr != S_OK) AfxThrowOleException(hr); hr = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);//建立LOCKBYTE對象 if (hr != S_OK) AfxThrowOleException(hr); ASSERT(lpLockBytes != NULL); hr = ::StgCreateDocfileOnILockBytes(lpLockBytes,//建立複合文檔 STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage); if (hr != S_OK) { VERIFY(lpLockBytes->Release() == 0); lpLockBytes = NULL; AfxThrowOleException(hr); } lpRichEditOle->GetClientSite(&lpOleClientSite); ZeroMemory(&reobject, sizeof(REOBJECT));//初始化一個對象 reobject.cbStruct = sizeof(REOBJECT); reobject.clsid = clsid; reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.dwFlags = REO_BELOWBASELINE; reobject.poleobj = lpOleObject; reobject.polesite = lpOleClientSite; reobject.pstg = lpStorage; lpOleObject->SetClientSite(lpOleClientSite);// hr = lpRichEditOle->InsertObject( &reobject ); if (hr != S_OK) AfxThrowOleException(hr); OleSetContainedObject(lpOleObject,TRUE); IPic->Load(_bstr_t(dlgOpen.GetPathName())); //裝載要顯示的圖像 } catch( COleException* e ) { TRACE(_T("OleException code:%d"),e->m_sc); e->Delete(); bRet = FALSE; } // release the interface //if( IPic != NULL ) IPic->Release(); if( lpOleObject != NULL ) lpOleObject->Release(); if( lpOleClientSite != NULL ) lpOleClientSite->Release(); if( lpStorage != NULL ) lpStorage->Release(); lpRichEditOle->Release(); }
還有個ATL實現播放GIF的源代碼
看了,還明白瞭如何去作了,但他的實現方式有問題,用線程去作的話,播放幾回那個CPU就無限地增大,卡死機
他是用pictureEx那個類來作的,本覺得是ipicture這個東西的問題,後來改爲了GDI+,image->draw(),但仍是出現了這種狀況,無耐啊
網上又有人說了,這個可能用定時器來作的話會好一點,
這位仁兄的,不知道是原創仍是轉載,反正就標着一個原字
http://blog.csdn.net/gxulg/article/details/299115
還有這位先生
http://blog.csdn.net/willnow/article/details/6456106
這個定時器類
// CTimer template <class Derived, class T, const IID* piid> class CTimer { public: CTimer() { m_bTimerOn = FALSE; } HRESULT TimerOn(DWORD dwTimerInterval) { Derived* pDerived = ((Derived*)this); m_dwTimerInterval = dwTimerInterval; if (m_bTimerOn) // already on, just change interval return S_OK; m_bTimerOn = TRUE; m_dwTimerInterval = dwTimerInterval; m_pStream = NULL; HRESULT hRes; hRes = CoMarshalInterThreadInterfaceInStream(*piid, (T*)pDerived, &m_pStream); // Create thread and pass the thread proc the this ptr m_hThread = CreateThread(NULL, 0, &_Apartment, (void*)this, 0, &m_dwThreadID); return S_OK; } void TimerOff() { if (m_bTimerOn) { m_bTimerOn = FALSE; AtlWaitWithMessageLoop(m_hThread); } } // Implementation private: static DWORD WINAPI _Apartment(void* pv) { CTimer<Derived, T, piid>* pThis = (CTimer<Derived, T, piid>*) pv; pThis->Apartment(); return 0; } DWORD Apartment() { CoInitialize(NULL); HRESULT hRes; m_spT.Release(); if (m_pStream) hRes = CoGetInterfaceAndReleaseStream(m_pStream, *piid, (void**)&m_spT); while(m_bTimerOn) { Sleep(m_dwTimerInterval); if (!m_bTimerOn) break; m_spT->_OnTimer(); } m_spT.Release(); CoUninitialize(); return 0; } // Attributes public: DWORD m_dwTimerInterval; // Implementation private: HANDLE m_hThread; DWORD m_dwThreadID; LPSTREAM m_pStream; CComPtr<T> m_spT; BOOL m_bTimerOn; };
折騰得夠慘了,哈哈
無心中也發現了這位兄弟的博客,找不到了地址了
但下載了他的源碼,並且還作了一個講解的PDF,夠用心的了,附上他的總結
/*****************************************************
實現 QQ表情這個功能的資料比較缺少,我也在網上找了比較久,根據網上找到的一些
相關資料,一點點嘗試實現的。
以上所述只是實現 QQ的表情功能的第一步,更深刻的內容我也在嘗試中,歡迎有興趣
的網友跟我一塊兒探討。
項目工程代碼我放在 QQ 羣:44177419,70934898,37950043 的羣共享上面。須要代碼
的能夠去那下載,也能夠直接發郵件來索取。代碼有錯誤的地方,歡迎發郵件指正。
個人聯繫方式:
QQ:xpmo@qq.com
MSN:msn@msn.com
郵箱:xpmo@qq.com
歡迎轉載,不過但願轉載時註明出處。
*****************************************************/
他的心聲跟我同樣,資料少啊
另外還有一個介紹 用VS2008+ATL開發Gif的ActiveX控件的步驟
http://blog.csdn.net/crybird/article/details/4049047
/****************************************************************
用VS2008+ATL開發顯示Gif的ActiveX控件
base:MSDN:開發語言-VS文檔-VC++-參考信息-庫參考-ATL-Concepts-ATL Tutorial
建立一個空的解決方案,名稱GifSolution。未來包含控件項目和測試項目。
解決方案視圖-右擊解決方案-添加-新建項目,彈出的對話框中選ATL項目,名稱爲GifAnimate肯定。彈出的對話框中選擇DLL服務器(可選容許合併代理存根,這樣不會產生代理dll),完成後編譯,這樣工程框架就完成了。
組件分有窗口的和無窗口的,這裏應該用有窗口的,因此添加組件的時候,外觀不要基於none,最好基於CStatic。由於gif是動態的,應該用另外一個線程繪製,這樣不影響主線程響應消息,繪圖更加流暢。
兩種窗口的區別:無窗口的控件用父窗口作本身的窗口;用父窗口的DC繪圖;經過DEFAULT_REFLECTION_HANDLER()把消息反饋給父窗口以進行響應。有窗口的控件,多一個CContainedWindow m_ctlStatic變量做爲顯示窗口;在BEGIN_MSG_MAP / END_MSG_MAP之間,經過ALT_MSG_MAP(1)宏映射消息處理(1爲控件m_ctlStatic構造時候的內部標記,由於可能有多個窗口,默認1個,用戶能夠本身添加)。
爲GifAnimate項目添加類-選擇ATL控件,點擊添加,彈出對話框。
第一卡:組件名稱GifAniControl
第二卡:支持鏈接點(由於要通知客戶端)
第三卡:默認接口
第四卡:外觀基於Static,可插入(在註冊表註冊爲OLE插入對象,能夠插入Office)
第五卡:實現固有屬性-背景色、邊框色、邊框可見性
肯定後,編譯經過。
類視圖-右鍵點擊控件接口-添加-方法,分別添加Play Stop Pause Continue PrevFrame NextFrame函數,以操做gif圖片。添加IsPlaying函數,添加LoadGifFromFile LoadGifFromStream函數
注意:在idl文件裏定義一個枚舉,指明播放方向。
類視圖-右鍵點擊控件接口-添加-屬性,分別添加Loop(循環次數) DelayTimeFactor(時間因子) PlayDirection(播放方向)等屬性。
對於每個屬性,控件類增長了一對函數,去讀寫屬性get/put_XXX,真正的變量要咱們本身寫的。
添加GifImage類,用於實現繪圖功能。
在控件類裏,添加一個GifImage類型的變量,主要用於對圖片的控制。
完成組件接口函數和屬性的調用。
把窗口的句柄給GifImage,讓它實現繪圖。
(對於無窗口控件,修改組件的OnDraw函數,實現繪圖)
編譯經過就能夠測試了(因爲用到了GDI+,用ActiveX控件測試容器沒法調用函數)。
右鍵點擊解決方案-添加-新建項目,彈出的對話框中選MFC EXE項目,名稱GifTestDlg。建立一個基於對話框的項目。
導入DLL:#import "../GifAnimate/Debug/GifAnimate.dll"
初始化COM和GDI+
在對話框初始化的時候建立控件,並設置屬性等。
編譯運行成功。
第二步已經支持鏈接點,idl文件裏會有事件接口
類視圖-右鍵點擊lib接口裏的事件接口-添加-方法,添加一個Click函數,參數爲long型的x,y座標。產生的效果是,在idl文件裏,嚮導爲事件接口添加了一個點擊函數。
生成一個代理類,實現函數。[Only in VC6, VS2008自動完成]
類視圖-右鍵點擊控件類-添加-添加鏈接點,在對話框選中以上提到的鏈接點,肯定。
代理類會包裝一個函數Fire_Click,觸發客戶端。
響應控件類的WM_LBUTTONDOWN消息,調用代理類的Fire_Click函數。
客戶端用ATL或者MFC完成一個接收器GifSink,鏈接、工做、斷開。
徹底能夠不作而經過程序設置屬性,作這個是給懶程序員用的,或者只是讓組件使用更方便。
添加-類-ATL屬性頁-肯定,彈出對話框中添加簡稱,修改組件屬性和標題,肯定。
系統生成相關的對話框卡片資源、對應對卡片類、idl相關內容、註冊腳本等。卡片類有一個Apply函數,用於接受屬性設置。
修改對話框,增長新控件等等。而後處理數據變化,例如:處理Edit的EN_CHANGE事件,設置page組件的髒數據標記(修改但沒有肯定)。最好並完成Apply函數。
在控件類.h添加以下代碼
PROP_ENTRY("Sides", 1, CLSID_GifProp)
1. 本文只是舉例說明開發過程,拋磚而已。
2. 樣例只是框架,不能直接使用,全部代碼沒有通過測試
3. 樣例接收器GifSink和屬性頁卡片沒有完成,懶了,呵呵
4. 樣例背景等不少屬性沒有實現
5. 使用了GDI+,但GDI+的Image類的SetActiveFrame函數有問題,網上貌似沒有解決辦法。Debug版本不影響使用,Release版本沒有測試。若是有興趣,可使用IPicture接口,網上不少。
6. 本文和本樣例版權crybird全部,引用處請標記crybird.
*****************************************************************************************************
說着說着,又找到那位兄弟的博客網址了附上
實現QQ表情功能(1)(2) http://blog.csdn.net/moxiaopeng/article/details/4211839
但經我實踐,有錯,是在運行時插入成功,但雙擊那張GIF圖片的時候,程序崩潰,但基本上也是按照上面的方法,用定時器去作的,總言之感謝分享!
那些高手都是滴水不漏的啊!
還有最後的QQ表情選擇面板
博客園裏面也有位同窗實現 了,還真不錯,感謝了
http://www.cnblogs.com/hoodlum1980/archive/2010/01/09/1642732.html
他是用cximage這個庫來實現 的,哎呀,BCB裏面也能夠用,但我怎樣試都是連接錯誤,NND,人品太差了
不過也太大了吧,不爽,應該用GDI+,由於網上也說了BCB裏面能夠用GDI+
但....
我就是用不了,不少方法了,csdn的老妖也有個說明,如何如何用的
也給貼上吧
用GDI+實現半透明漸變的特效窗口
http://www.ccrun.com/article.asp?i=643&d=n5u8o4
/**************************************************************************************
方法:在C++Builder中使用GDI+的方法和代碼網上遍地都是,這裏爲了完整性,簡單說說流程:
1.) 在BCB6中已自帶了ghiplus.h文件,故只須要生成gdiplus.lib文件就能夠:
在命令行下運行implib gdiplus.lib gdiplus.dll。(若是ghiplus.dll不在當前文件夾下,注意寫完整路徑)
2.) 在工程的編譯選項中加入STRICT條件編譯:
Project-->Options-->Directories/Conditionals-->Condtionals-->點擊旁邊的"..."按鈕-->輸入STRICT,而後Add。
3.) 在工程中加入Gdiplus.lib:
Project-->Add To Project-->找到Gdiplus.lib添加進來。
4.) 在工程的.h文件中包含所需的頭文件,注意前後順序:
#include "math.hpp"
#include <algorithm>
using std::min;
using std::max;
#include "gdiplus.h"
using namespace Gdiplus;
****************************************************************************/
也按上面的方法作了,也能夠在image對象調用draw方法了
但在設置顯示幀的時候
UINT nCount = pImg->GetFrameDimensionsCount(); GUID* pDimensionIDs =new GUID[nCount]; pImg->GetFrameDimensionsList(pDimensionIDs, nCount); m_nTotalFrame = pImg->GetFrameCount(&pDimensionIDs[0]); //PropertyTagFrameDelay是GDI+中預約義的一個GIG屬性ID值,表示標籤幀數據的延遲時間 UINT nSize = pImg->GetPropertyItemSize(PropertyTagFrameDelay); m_pPropertyItem = (PropertyItem*)malloc(nSize); pImg->GetPropertyItem(PropertyTagFrameDelay,nSize,m_pPropertyItem);
[Linker Error] Unresolved external '_FrameDimensionTime' referenced from
這個你也太欺負人了吧,不是坑爹嗎?!
我又改爲pictureEx那個類的顯示GIF,終因而作好了,上個圖
還有不少東西要作啊
哈哈,利用BCB編譯的時間來寫這個,TMD BCB你也編譯得太快了吧
總論BCB不是個好東西!!!
第一次寫博客,還給博客嚇了一跳,覺得保存到草稿箱的找不出來的呢,哈哈!