Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

415 lines
11 KiB

  1. /******************************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. Behav_BITMAP.cpp
  5. Abstract:
  6. This file contains the implementation of the CPCHBehavior_BITMAP class,
  7. that renders bitmap images with 8-bit alpha channel.
  8. Revision History:
  9. Davide Massarenti (dmassare) 25/03/2001
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. ////////////////////////////////////////////////////////////////////////////////
  14. static HBITMAP CreateMirroredBitmap( /*[in]*/ HBITMAP hbmOrig, /*[in]*/ BITMAP& bm )
  15. {
  16. HBITMAP hbmMirrored = NULL;
  17. HDC hdc = ::GetDC( NULL ); // Grab the screen DC
  18. if(hdc)
  19. {
  20. HDC hdcMem1 = ::CreateCompatibleDC( hdc );
  21. if(hdcMem1)
  22. {
  23. HDC hdcMem2 = ::CreateCompatibleDC( hdc );
  24. if(hdcMem2)
  25. {
  26. BITMAPINFO bi = { sizeof(BITMAPINFOHEADER), bm.bmWidth, bm.bmHeight, 1, 32 };
  27. void* p;
  28. hbmMirrored = ::CreateDIBSection( hdc, &bi, DIB_RGB_COLORS, &p, NULL, 0 );
  29. if(hbmMirrored)
  30. {
  31. HBITMAP hOld_bm1 = (HBITMAP)SelectObject( hdcMem1, hbmOrig );
  32. HBITMAP hOld_bm2 = (HBITMAP)SelectObject( hdcMem2, hbmMirrored );
  33. //
  34. // Flip the bitmap
  35. //
  36. ::SetLayout( hdcMem2, LAYOUT_RTL );
  37. ::BitBlt ( hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem1, 0, 0, SRCCOPY );
  38. ::SelectObject( hdcMem2, hOld_bm2 );
  39. ::SelectObject( hdcMem1, hOld_bm1 );
  40. }
  41. ::DeleteDC( hdcMem2 );
  42. }
  43. ::DeleteDC( hdcMem1 );
  44. }
  45. ::ReleaseDC( NULL, hdc );
  46. }
  47. return hbmMirrored;
  48. }
  49. ////////////////////////////////////////////////////////////////////////////////
  50. static const CPCHBehavior::EventDescription s_events[] =
  51. {
  52. { L"onpropertychange", DISPID_HTMLELEMENTEVENTS_ONPROPERTYCHANGE },
  53. { L"onmousedown" , DISPID_HTMLELEMENTEVENTS_ONMOUSEDOWN },
  54. { L"onmouseup" , DISPID_HTMLELEMENTEVENTS_ONMOUSEUP },
  55. { L"onmouseout" , DISPID_HTMLELEMENTEVENTS_ONMOUSEOUT },
  56. { L"onmouseover" , DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER },
  57. { NULL },
  58. };
  59. ////////////////////////////////////////////////////////////////////////////////
  60. CPCHBehavior_BITMAP::CPCHBehavior_BITMAP()
  61. {
  62. __HCP_FUNC_ENTRY( "CPCHBehavior_BITMAP::CPCHBehavior_BITMAP" );
  63. // CComBSTR m_bstrBaseURL;
  64. // CComBSTR m_bstrImage;
  65. //
  66. // CComBSTR m_bstrImageNormal;
  67. // CComBSTR m_bstrImageMouseOver;
  68. // CComBSTR m_bstrImageMouseDown;
  69. m_fFlipH = false; // bool m_fFlipH;
  70. m_fAutoRTL = true; // bool m_fAutoRTL;
  71. //
  72. m_himl = NULL; // HIMAGELIST m_himl;
  73. m_hBMP = NULL; // HBITMAP m_hBMP;
  74. // BITMAP m_bm;
  75. m_lWidth = 0; // LONG m_lWidth;
  76. m_lHeight = 0; // LONG m_lHeight;
  77. //
  78. m_fMouseOver = false; // bool m_fMouseOver;
  79. m_fMouseDown = false; // bool m_fMouseDown;
  80. }
  81. CPCHBehavior_BITMAP::~CPCHBehavior_BITMAP()
  82. {
  83. ReleaseImage( /*fOnlyIL*/false );
  84. }
  85. /////////////////////////////////////////////////////////////////////////////
  86. #ifndef ILC_COLORMASK
  87. #define ILC_COLORMASK 0x00FE
  88. #define ILD_BLENDMASK 0x000E
  89. #endif
  90. void CPCHBehavior_BITMAP::ReleaseImage( /*[in]*/ bool fOnlyIL )
  91. {
  92. if(m_himl)
  93. {
  94. (void)::ImageList_Destroy( m_himl ); m_himl = NULL;
  95. m_lWidth = 0;
  96. m_lHeight = 0;
  97. }
  98. if(!fOnlyIL)
  99. {
  100. if(m_hBMP)
  101. {
  102. (void)::DeleteObject( m_hBMP ); m_hBMP = NULL;
  103. }
  104. }
  105. }
  106. HRESULT CPCHBehavior_BITMAP::GrabImage()
  107. {
  108. __HCP_FUNC_ENTRY( "CPCHBehavior_BITMAP::GrabImage" );
  109. HRESULT hr;
  110. if(m_hBMP == NULL)
  111. {
  112. COLORREF crMask = RGB( 255, 0, 255 );
  113. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::HTML::DownloadBitmap( m_bstrBaseURL, m_bstrImage, crMask, m_hBMP ));
  114. if(::GetObject( m_hBMP, sizeof(m_bm), &m_bm ) != sizeof(m_bm))
  115. {
  116. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  117. }
  118. if(m_fFlipH || (m_fAutoRTL && m_fRTL))
  119. {
  120. HBITMAP hbmMirrored;
  121. __MPC_EXIT_IF_ALLOC_FAILS(hr, hbmMirrored, CreateMirroredBitmap( m_hBMP, m_bm ));
  122. (void)::DeleteObject( m_hBMP ); m_hBMP = hbmMirrored;
  123. if(::GetObject( m_hBMP, sizeof(m_bm), &m_bm ) != sizeof(m_bm))
  124. {
  125. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  126. }
  127. }
  128. }
  129. hr = S_OK;
  130. __HCP_FUNC_CLEANUP;
  131. __HCP_FUNC_EXIT(hr);
  132. }
  133. HRESULT CPCHBehavior_BITMAP::ScaleImage( /*[in]*/ LPRECT prc )
  134. {
  135. __HCP_FUNC_ENTRY( "CPCHBehavior_BITMAP::ScaleImage" );
  136. HRESULT hr;
  137. LONG lWidth = prc->right - prc->left;
  138. LONG lHeight = prc->bottom - prc->top;
  139. HBITMAP hBMPScaled = NULL;
  140. __MPC_EXIT_IF_METHOD_FAILS(hr, GrabImage());
  141. if(m_lWidth != lWidth ||
  142. m_lHeight != lHeight ||
  143. m_himl == NULL )
  144. {
  145. COLORREF crMask = RGB( 255, 0, 255 );
  146. UINT flags = 0;
  147. ReleaseImage( /*fOnlyIL*/true );
  148. if(m_bm.bmWidth != lWidth ||
  149. m_bm.bmHeight != lHeight )
  150. {
  151. hBMPScaled = (HBITMAP)::CopyImage( m_hBMP, IMAGE_BITMAP, lWidth, lHeight, LR_CREATEDIBSECTION );
  152. if(hBMPScaled == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_OUTOFMEMORY);
  153. }
  154. if(crMask != CLR_NONE) flags |= ILC_MASK;
  155. if(m_bm.bmBits) flags |= (m_bm.bmBitsPixel & ILC_COLORMASK);
  156. m_himl = ::ImageList_Create( lWidth, lHeight, flags, 1, 1 );
  157. if(m_himl == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_OUTOFMEMORY);
  158. if(::ImageList_AddMasked( m_himl, hBMPScaled ? hBMPScaled : m_hBMP, crMask ) < 0)
  159. {
  160. ReleaseImage( /*fOnlyIL*/true );
  161. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  162. }
  163. m_lWidth = lWidth;
  164. m_lHeight = lHeight;
  165. }
  166. hr = S_OK;
  167. __HCP_FUNC_CLEANUP;
  168. if(hBMPScaled) ::DeleteObject( hBMPScaled );
  169. __HCP_FUNC_EXIT(hr);
  170. }
  171. HRESULT CPCHBehavior_BITMAP::RefreshImages()
  172. {
  173. __HCP_FUNC_ENTRY( "CPCHBehavior_BITMAP::RefreshImages" );
  174. HRESULT hr;
  175. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::COMUtil::GetPropertyByName( m_elem, L"srcNormal" , m_bstrImageNormal ));
  176. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::COMUtil::GetPropertyByName( m_elem, L"srcMouseOver", m_bstrImageMouseOver ));
  177. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::COMUtil::GetPropertyByName( m_elem, L"srcMouseDown", m_bstrImageMouseDown ));
  178. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::COMUtil::GetPropertyByName( m_elem, L"FlipH" , m_fFlipH ));
  179. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::COMUtil::GetPropertyByName( m_elem, L"AutoRTL" , m_fAutoRTL ));
  180. hr = S_OK;
  181. __HCP_FUNC_CLEANUP;
  182. __HCP_FUNC_EXIT(hr);
  183. }
  184. HRESULT CPCHBehavior_BITMAP::onMouse( DISPID id, DISPPARAMS*, VARIANT* )
  185. {
  186. __HCP_FUNC_ENTRY( "CPCHBehavior_BITMAP::onMouse" );
  187. HRESULT hr;
  188. BSTR bstrCurrentImage = NULL;
  189. switch(id)
  190. {
  191. case DISPID_HTMLELEMENTEVENTS_ONPROPERTYCHANGE: __MPC_EXIT_IF_METHOD_FAILS(hr, RefreshImages()); break;
  192. case DISPID_HTMLELEMENTEVENTS_ONMOUSEDOWN: m_fMouseDown = true ; break;
  193. case DISPID_HTMLELEMENTEVENTS_ONMOUSEUP : m_fMouseDown = false; break;
  194. case DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER: m_fMouseOver = true ; break;
  195. case DISPID_HTMLELEMENTEVENTS_ONMOUSEOUT : m_fMouseDown = false; m_fMouseOver = false; break;
  196. }
  197. if (m_fMouseDown && m_bstrImageMouseDown) bstrCurrentImage = m_bstrImageMouseDown;
  198. else if(m_fMouseOver && m_bstrImageMouseOver) bstrCurrentImage = m_bstrImageMouseOver;
  199. else bstrCurrentImage = m_bstrImageNormal;
  200. if(bstrCurrentImage && MPC::StrCmp( bstrCurrentImage, m_bstrImage ))
  201. {
  202. CComQIPtr<IElementBehaviorSiteRender> render;
  203. ReleaseImage( /*fOnlyIL*/false );
  204. m_bstrImage = bstrCurrentImage;
  205. render = m_siteOM;
  206. if(render)
  207. {
  208. (void)render->InvalidateRenderInfo();
  209. }
  210. }
  211. hr = S_OK;
  212. __HCP_FUNC_CLEANUP;
  213. __HCP_FUNC_EXIT(hr);
  214. }
  215. /////////////////////////////////////////////////////////////////////////////
  216. STDMETHODIMP CPCHBehavior_BITMAP::Init( /*[in]*/ IElementBehaviorSite* pBehaviorSite )
  217. {
  218. __HCP_FUNC_ENTRY( "CPCHBehavior_BITMAP::Init" );
  219. HRESULT hr;
  220. CComPtr<IHTMLDocument2> doc;
  221. CComPtr<IHTMLLocation> loc;
  222. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior::Init( pBehaviorSite ));
  223. __MPC_EXIT_IF_METHOD_FAILS(hr, AttachToEvents( s_events, (CLASS_METHOD)onMouse ));
  224. //
  225. // We need to set the font size to something really small or Trident will enlarge the element.
  226. //
  227. {
  228. CComPtr<IHTMLStyle> pStyle;
  229. if(SUCCEEDED(m_elem->get_style( &pStyle )) && pStyle)
  230. {
  231. CComVariant v( L"1px" );
  232. (void)pStyle->put_fontSize( v );
  233. }
  234. }
  235. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::HTML::IDispatch_To_IHTMLDocument2( doc, m_elem ));
  236. __MPC_EXIT_IF_METHOD_FAILS(hr, doc->get_location( &loc ));
  237. __MPC_EXIT_IF_METHOD_FAILS(hr, loc->get_href( &m_bstrBaseURL ));
  238. __MPC_EXIT_IF_METHOD_FAILS(hr, RefreshImages());
  239. m_bstrImage = m_bstrImageNormal;
  240. hr = S_OK;
  241. __HCP_FUNC_CLEANUP;
  242. __HCP_FUNC_EXIT(hr);
  243. }
  244. ////////////////////////////////////////////////////////////////////////////////
  245. STDMETHODIMP CPCHBehavior_BITMAP::Draw( /*[in]*/ RECT rcBounds ,
  246. /*[in]*/ RECT rcUpdate ,
  247. /*[in]*/ LONG lDrawFlags ,
  248. /*[in]*/ HDC hdc ,
  249. /*[in]*/ LPVOID pvDrawObject )
  250. {
  251. if(SUCCEEDED(ScaleImage( &rcBounds )))
  252. {
  253. if(m_himl)
  254. {
  255. IMAGELISTDRAWPARAMS imldp; ::ZeroMemory( &imldp, sizeof(imldp) );
  256. imldp.cbSize = sizeof(imldp);
  257. imldp.himl = m_himl;
  258. imldp.i = 0;
  259. imldp.hdcDst = hdc;
  260. imldp.x = rcBounds.left;
  261. imldp.y = rcBounds.top;
  262. imldp.cx = 0;
  263. imldp.cy = 0;
  264. imldp.xBitmap = 0;
  265. imldp.yBitmap = 0;
  266. imldp.rgbBk = CLR_NONE;
  267. imldp.rgbFg = CLR_DEFAULT;
  268. imldp.fStyle = ILD_TRANSPARENT;
  269. imldp.fState = 0;
  270. imldp.Frame = 0;
  271. ::ImageList_DrawIndirect( &imldp );
  272. }
  273. }
  274. return S_OK;
  275. }
  276. STDMETHODIMP CPCHBehavior_BITMAP::GetPainterInfo( /*[in]*/ HTML_PAINTER_INFO *pInfo )
  277. {
  278. if(pInfo)
  279. {
  280. pInfo->lFlags = HTMLPAINTER_TRANSPARENT;
  281. pInfo->lZOrder = HTMLPAINT_ZORDER_BELOW_CONTENT;
  282. pInfo->iidDrawObject = IID_NULL;
  283. pInfo->rcExpand.left = 0;
  284. pInfo->rcExpand.top = 0;
  285. pInfo->rcExpand.right = 0;
  286. pInfo->rcExpand.bottom = 0;
  287. }
  288. return S_OK;
  289. }
  290. STDMETHODIMP CPCHBehavior_BITMAP::HitTestPoint( /*[in]*/ POINT pt ,
  291. /*[in]*/ BOOL* pbHit ,
  292. /*[in]*/ LONG* plPartID )
  293. {
  294. return E_NOTIMPL;
  295. }
  296. STDMETHODIMP CPCHBehavior_BITMAP::OnResize( /*[in]*/ SIZE pt )
  297. {
  298. return E_NOTIMPL;
  299. }