Source code of Windows XP (NT5)
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.

208 lines
3.9 KiB

  1. // DeviceIcon.cpp : Implementation of CDeviceIcon
  2. #include "stdafx.h"
  3. #include "DevCon2.h"
  4. #include "DeviceIcon.h"
  5. #include "Device.h"
  6. #include "SetupClass.h"
  7. /////////////////////////////////////////////////////////////////////////////
  8. // CDeviceIcon
  9. //
  10. // SetupDiLoadClassIcon(guid,&hIcon,&miniicon)
  11. // SetupDiDrawMiniIcon(....)
  12. //
  13. void CDeviceIcon::ResetIcon()
  14. {
  15. if(m_hIcon) {
  16. DestroyIcon(m_hIcon);
  17. m_hIcon = NULL;
  18. }
  19. if(m_hSmallImage) {
  20. DeleteObject(m_hSmallImage);
  21. m_hSmallImage = NULL;
  22. }
  23. if(m_hSmallMask) {
  24. DeleteObject(m_hSmallMask);
  25. m_hSmallMask = NULL;
  26. }
  27. }
  28. HRESULT CDeviceIcon::OnDraw(ATL_DRAWINFO& di)
  29. {
  30. if(!m_hIcon) {
  31. return S_OK;
  32. }
  33. RECT rect = *(RECT*)di.prcBounds;
  34. int asp_x;
  35. int asp_y;
  36. int asp;
  37. asp_x = rect.right-rect.left;
  38. asp_y = rect.bottom-rect.top;
  39. asp = min(asp_x,asp_y);
  40. if(asp>=32) {
  41. asp = 32;
  42. } else {
  43. asp = 16;
  44. }
  45. rect.left += (asp_x-asp)/2;
  46. rect.top += (asp_y-asp)/2;
  47. rect.right = rect.left+asp;
  48. rect.bottom = rect.top+asp;
  49. if(asp == 16) {
  50. //
  51. // draw mini-icon
  52. // this is complex because of the way SetupDiDrawMiniIcon works
  53. // and we want this to be like a real icon when placed on a web page
  54. //
  55. DrawMiniIcon(di.hdcDraw,rect,m_MiniIcon);
  56. } else {
  57. //
  58. // draw regular icon
  59. //
  60. DrawIcon(di.hdcDraw,rect.left,rect.top,m_hIcon);
  61. }
  62. return S_OK;
  63. }
  64. BOOL CDeviceIcon::DrawMiniIcon(HDC hDC, RECT &rect,INT icon)
  65. {
  66. HBITMAP hbmOld;
  67. HDC hdcMem;
  68. hdcMem = CreateCompatibleDC(hDC);
  69. if(!hdcMem) {
  70. return FALSE;
  71. }
  72. if(!(m_hSmallImage && m_hSmallMask)) {
  73. //
  74. // create bitmaps (once)
  75. //
  76. if(!m_hSmallImage) {
  77. m_hSmallImage = CreateCompatibleBitmap(hDC,rect.right-rect.left,rect.bottom-rect.top);
  78. if(!m_hSmallImage) {
  79. DeleteDC(hdcMem);
  80. return FALSE;
  81. }
  82. }
  83. if(!m_hSmallMask) {
  84. m_hSmallMask = CreateBitmap(rect.right-rect.left,rect.bottom-rect.top,1,1,NULL);
  85. if(!m_hSmallMask) {
  86. DeleteDC(hdcMem);
  87. return FALSE;
  88. }
  89. }
  90. //
  91. // obtain the bitmap data (once)
  92. //
  93. RECT memRect;
  94. memRect.left = memRect.top = 0;
  95. memRect.right = rect.right-rect.left;
  96. memRect.bottom = rect.bottom-rect.top;
  97. //
  98. // mask first
  99. //
  100. hbmOld = (HBITMAP)SelectObject(hdcMem,m_hSmallMask);
  101. SetupDiDrawMiniIcon(hdcMem,memRect,icon,DMI_USERECT|DMI_MASK);
  102. //
  103. // now source
  104. //
  105. SelectObject(hdcMem,m_hSmallImage);
  106. SetupDiDrawMiniIcon(hdcMem,memRect,icon,DMI_USERECT);
  107. } else {
  108. //
  109. // select source
  110. //
  111. hbmOld = (HBITMAP)SelectObject(hdcMem,m_hSmallImage);
  112. }
  113. //
  114. // now blt image via mask
  115. //
  116. if(GetDeviceCaps(hDC,RASTERCAPS)&RC_BITBLT) {
  117. //
  118. // draw icon using mask
  119. //
  120. MaskBlt(hDC,
  121. rect.left,
  122. rect.top,
  123. rect.right-rect.left,
  124. rect.bottom-rect.top,
  125. hdcMem,
  126. 0,
  127. 0,
  128. m_hSmallMask,
  129. 0,
  130. 0,
  131. MAKEROP4(0xAA0029,SRCCOPY) // 0xAA0029 (from MSDN) = transparent
  132. );
  133. }
  134. SelectObject(hdcMem,hbmOld);
  135. DeleteDC(hdcMem);
  136. return TRUE;
  137. }
  138. STDMETHODIMP CDeviceIcon::ObtainIcon(LPDISPATCH pSource)
  139. {
  140. HRESULT hr;
  141. CComQIPtr<IDeviceInternal> pDevice;
  142. CComQIPtr<ISetupClassInternal> pSetupClass;
  143. BSTR pMachine = NULL;
  144. GUID cls;
  145. HICON hIcon;
  146. INT miniIcon;
  147. if(!pSource) {
  148. ResetIcon();
  149. return S_OK;
  150. }
  151. pSetupClass = pSource;
  152. pDevice = pSource;
  153. if(pSetupClass) {
  154. //
  155. // obtain icon for specified device/class
  156. // based on devices class
  157. //
  158. hr = pSetupClass->get__Machine(&pMachine);
  159. if(FAILED(hr)) {
  160. pMachine = NULL;
  161. } else {
  162. hr = pSetupClass->get__ClassGuid(&cls);
  163. }
  164. if(FAILED(hr)) {
  165. cls = GUID_DEVCLASS_UNKNOWN;
  166. }
  167. //
  168. // obtain icon
  169. //
  170. if(!SetupDiLoadClassIcon(&cls,&hIcon,&miniIcon)) {
  171. cls = GUID_DEVCLASS_UNKNOWN;
  172. if(!SetupDiLoadClassIcon(&cls,&hIcon,&miniIcon)) {
  173. DWORD err = GetLastError();
  174. SysFreeString(pMachine);
  175. return HRESULT_FROM_SETUPAPI(err);
  176. }
  177. }
  178. ResetIcon();
  179. m_hIcon = hIcon;
  180. m_MiniIcon = miniIcon;
  181. FireViewChange();
  182. if(pMachine) {
  183. SysFreeString(pMachine);
  184. }
  185. return S_OK;
  186. } else {
  187. return E_INVALIDARG;
  188. }
  189. }