ATL制作的显示GIF的控件,遇到的有关问题.请朋友们帮忙.多谢
ATL制作的显示GIF的控件,遇到的问题.请朋友们帮忙.谢谢
继续请朋友们帮忙.
做的这个显示GIF的控件,是用一个线程绘制GIF图片的每一帧.原来在线程中是用FireViewChange来触发OnDraw进行当前帧的绘制,发现当在CRichEditCtrl的同一行中插入两个图片时,程序占用CPU资源极高,说明FireViewChange是通知容器重绘,两个控件彼此不断调用各自的OnDraw,从而造成程序占用CPU使用率极高. 后来,在线程中使用Invalidate来执行控件重绘,在插入到CRichEditCtrl后,发现,控件的m_bInPlaceActive为TRUE时,一切正常,但当CRichEditCtrl取得焦点后,或在CRichEditCtrl中输入文字时,控件的m_bInPlaceActive被自动置为FALSE,同时线程中调用Invalidate也失败,并且也无法调用m_spInPlaceSite的InvalidateRect来绘制GIF的当前帧.因此,想请教朋友们,是否可能有办法设置m_bInPlaceActive始终为TRUE,或者如何在除Ondraw函数外,在绘制GIF的线程中,取得规范化的绘图设备和绘图区域?谢谢。
------解决方案--------------------
这是我写的atl控件部分代码
继续请朋友们帮忙.
做的这个显示GIF的控件,是用一个线程绘制GIF图片的每一帧.原来在线程中是用FireViewChange来触发OnDraw进行当前帧的绘制,发现当在CRichEditCtrl的同一行中插入两个图片时,程序占用CPU资源极高,说明FireViewChange是通知容器重绘,两个控件彼此不断调用各自的OnDraw,从而造成程序占用CPU使用率极高. 后来,在线程中使用Invalidate来执行控件重绘,在插入到CRichEditCtrl后,发现,控件的m_bInPlaceActive为TRUE时,一切正常,但当CRichEditCtrl取得焦点后,或在CRichEditCtrl中输入文字时,控件的m_bInPlaceActive被自动置为FALSE,同时线程中调用Invalidate也失败,并且也无法调用m_spInPlaceSite的InvalidateRect来绘制GIF的当前帧.因此,想请教朋友们,是否可能有办法设置m_bInPlaceActive始终为TRUE,或者如何在除Ondraw函数外,在绘制GIF的线程中,取得规范化的绘图设备和绘图区域?谢谢。
------解决方案--------------------
这是我写的atl控件部分代码
- C/C++ code
HWND OleImageRe::GetContainerWindow() { HWND hwnd = NULL; HRESULT hr; //*****这段代码在VC++ 工作 if (m_spInPlaceSite != NULL) { m_spInPlaceSite->GetWindow(&hwnd); return hwnd; } //****** 这段代码在Visual Basic工作 LPOLECLIENTSITE pOleClientSite = NULL; GetClientSite(&pOleClientSite); if ( pOleClientSite ) { IOleWindow* pOleWindow; hr = pOleClientSite->QueryInterface( IID_IOleWindow, (LPVOID*)&pOleWindow ); if ( pOleWindow ) { pOleWindow->GetWindow( &hwnd ); pOleWindow->Release(); return hwnd; } } return NULL; } HWND OleImageRe::GetDisplayWndRect(RECT * pRect) { HWND hWnd = GetContainerWindow(); if (pRect) { RECT rcPos, rcClip; if (m_hWndCD) { hWnd = m_hWndCD; ::GetClientRect(hWnd,&rcPos); *pRect = rcPos; } else { if (::IsWindow(hWnd) && m_spInPlaceSite) { CComPtr<IOleInPlaceFrame> spInPlaceFrame; CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow; OLEINPLACEFRAMEINFO frameInfo; frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); m_spInPlaceSite->GetWindowContext(&spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo); if (rcPos.right < rcClip.left || rcPos.bottom < rcClip.top || rcPos.left > rcClip.right || rcPos.top > rcClip.bottom) { // 判断是否超出显示范围 } else { *pRect = rcPos; } } } } return hWnd; }
------解决方案--------------------
不知道你是怎么写的,我是基于Static控件
- C/C++ code
//在 LRESULT CGifRender::OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (num)//总帧数 { if (m_CurrenPicture<num-1) { m_CurrenPicture++;//更新当前帧 } else m_CurrenPicture=0; } HDC dc=m_ctlStatic.GetDC();//获得DC Render(dc); //绘制当前帧 m_ctlStatic.ReleaseDC(dc); return 0; }