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.

233 lines
6.8 KiB

  1. /*******************************************************************************
  2. * OwnerDrawUI.inl *
  3. *-----------------*
  4. * Description:
  5. * This is the header file for user-interface helper functions. Note that
  6. * unlike SpHelper.H, this file requires the use of ATL.
  7. * Unlike spuihelp.h, this will take care of displaying DBCS characters
  8. * (non-native-codepage)
  9. *
  10. * PLEASE NOTE: In order for this to work, the caller must I mean must
  11. * process WM_DRAWITEM messages and call DrawODTokenListItem()!!!
  12. *-------------------------------------------------------------------------------
  13. * Copyright (c) Microsoft Corporation. All rights reserved.
  14. *******************************************************************************/
  15. #ifndef __sapi_h__
  16. #include <sapi.h>
  17. #endif
  18. #ifndef SPError_h
  19. #include <SPError.h>
  20. #endif
  21. #ifndef SPDebug_h
  22. #include <SPDebug.h>
  23. #endif
  24. #ifndef __ATLBASE_H__
  25. #include <ATLBASE.h>
  26. #endif
  27. #ifndef __ATLCONV_H__
  28. #include <ATLCONV.H>
  29. #endif
  30. inline HRESULT InitODTokenList(UINT MsgAddString, UINT MsgSetItemData, UINT MsgSetCurSel,
  31. HWND hwnd, const WCHAR * pszCatName,
  32. const WCHAR * pszRequiredAttrib, const WCHAR * pszOptionalAttrib)
  33. {
  34. HRESULT hr;
  35. ISpObjectToken * pToken; // NOTE: Not a CComPtr! Be Careful.
  36. CComPtr<IEnumSpObjectTokens> cpEnum;
  37. hr = SpEnumTokens(pszCatName, pszRequiredAttrib, pszOptionalAttrib, &cpEnum);
  38. UINT cItems = 0;
  39. if (hr == S_OK)
  40. {
  41. bool fSetDefault = false;
  42. while (cpEnum->Next(1, &pToken, NULL) == S_OK)
  43. {
  44. if (SUCCEEDED(hr))
  45. {
  46. // This sets the thing as item data, since this CB is ownerdraw
  47. LRESULT i = ::SendMessage(hwnd, MsgAddString, 0, (LPARAM) pToken);
  48. if (i == CB_ERR || i == CB_ERRSPACE) // Note: CB_ and LB_ errors are identical values...
  49. {
  50. hr = E_OUTOFMEMORY;
  51. }
  52. else
  53. {
  54. if (!fSetDefault)
  55. {
  56. ::SendMessage(hwnd, MsgSetCurSel, i, 0);
  57. fSetDefault = true;
  58. }
  59. cItems++;
  60. }
  61. }
  62. if (FAILED(hr))
  63. {
  64. pToken->Release();
  65. }
  66. }
  67. }
  68. else
  69. {
  70. hr = SPERR_NO_MORE_ITEMS;
  71. }
  72. if ( SUCCEEDED( hr ) && (0 == cItems) )
  73. {
  74. hr = S_FALSE;
  75. }
  76. return hr;
  77. }
  78. inline HRESULT InitODTokenComboBox(HWND hwnd, const WCHAR * pszCatName,
  79. const WCHAR * pszRequiredAttrib = NULL, const WCHAR * pszOptionalAttrib = NULL)
  80. {
  81. return InitODTokenList(CB_ADDSTRING, CB_SETITEMDATA, CB_SETCURSEL, hwnd, pszCatName, pszRequiredAttrib, pszOptionalAttrib);
  82. }
  83. //
  84. // Dont call this function directly. Use DestoyTokenODComboBox or DestroyTokenODListBox.
  85. //
  86. inline void DestroyODTokenList(UINT MsgGetCount, UINT MsgGetItemData, HWND hwnd)
  87. {
  88. LRESULT c = ::SendMessage(hwnd, MsgGetCount, 0, 0);
  89. for (LRESULT i = 0; i < c; i++)
  90. {
  91. IUnknown * pUnkObj = (IUnknown *)::SendMessage(hwnd, MsgGetItemData, i, 0);
  92. if (pUnkObj)
  93. {
  94. pUnkObj->Release();
  95. }
  96. }
  97. }
  98. inline void DestroyODTokenComboBox(HWND hwnd)
  99. {
  100. DestroyODTokenList(CB_GETCOUNT, CB_GETITEMDATA, hwnd);
  101. }
  102. inline ISpObjectToken * GetODComboBoxToken(HWND hwnd, WPARAM Index)
  103. {
  104. return (ISpObjectToken *)::SendMessage(hwnd, CB_GETITEMDATA, Index, 0);
  105. }
  106. inline ISpObjectToken * GetCurSelODComboBoxToken(HWND hwnd)
  107. {
  108. LRESULT i = ::SendMessage(hwnd, CB_GETCURSEL, 0, 0);
  109. return (i == CB_ERR) ? NULL : GetODComboBoxToken(hwnd, i);
  110. }
  111. inline void UpdateCurSelODComboBoxToken(HWND hwnd)
  112. {
  113. // Repainting the window will get the correct text displayed
  114. ::InvalidateRect( hwnd, NULL, TRUE );
  115. }
  116. // Don't call this directly.
  117. inline HRESULT AddTokenToODList(UINT MsgAddString, UINT MsgSetItemData, UINT MsgSetCurSel, HWND hwnd, ISpObjectToken * pToken)
  118. {
  119. HRESULT hr = S_OK;
  120. USES_CONVERSION;
  121. LRESULT i = ::SendMessage(hwnd, MsgAddString, 0, (LPARAM)pToken);
  122. if (i == CB_ERR || i == CB_ERRSPACE) // Note: CB_ and LB_ errors are identical values...
  123. {
  124. hr = E_OUTOFMEMORY;
  125. }
  126. else
  127. {
  128. ::SendMessage(hwnd, MsgSetCurSel, i, 0);
  129. pToken->AddRef();
  130. }
  131. }
  132. inline HRESULT AddTokenToODComboBox(HWND hwnd, ISpObjectToken * pToken)
  133. {
  134. return AddTokenToODList(CB_ADDSTRING, CB_SETITEMDATA, CB_SETCURSEL, hwnd, pToken);
  135. }
  136. // Don't call this directly
  137. inline HRESULT DeleteCurSelODToken(UINT MsgGetCurSel, UINT MsgSetCurSel, UINT MsgGetItemData, UINT MsgDeleteString, HWND hwnd)
  138. {
  139. HRESULT hr = S_OK;
  140. LRESULT i = ::SendMessage(hwnd, MsgGetCurSel, 0, 0);
  141. if (i == CB_ERR)
  142. {
  143. hr = S_FALSE;
  144. }
  145. else
  146. {
  147. ISpObjectToken * pToken = (ISpObjectToken *)::SendMessage(hwnd, MsgGetItemData, i, 0);
  148. if (pToken)
  149. {
  150. pToken->Release();
  151. }
  152. ::SendMessage(hwnd, MsgDeleteString, i, 0);
  153. ::SendMessage(hwnd, MsgSetCurSel, i, 0);
  154. }
  155. return hr;
  156. }
  157. inline HRESULT DeleteCurSelODComboBoxToken(HWND hwnd)
  158. {
  159. return DeleteCurSelODToken(CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_DELETESTRING, hwnd);
  160. }
  161. // The owner of the owner-draw control MUST call this upon receiving a WM_DRAWITEM message
  162. void DrawODTokenListItem( LPDRAWITEMSTRUCT lpdis )
  163. {
  164. UINT oldTextAlign = GetTextAlign(lpdis->hDC);
  165. COLORREF clrfTextOld = ::GetTextColor( lpdis->hDC );
  166. COLORREF clrfBkOld = ::GetBkColor( lpdis->hDC );
  167. // Get the item state and change colors accordingly
  168. if ( (ODS_DISABLED & lpdis->itemState) || (-1 == lpdis->itemID) )
  169. {
  170. ::SetTextColor( lpdis->hDC, ::GetSysColor( COLOR_GRAYTEXT ) );
  171. }
  172. else if ( ODS_SELECTED & lpdis->itemState )
  173. {
  174. // Set the text background and foreground colors
  175. SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  176. SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
  177. }
  178. UINT options = ETO_OPAQUE | ETO_CLIPPED;
  179. // Strings are stored as item data
  180. CSpDynamicString dstrName;
  181. if ( -1 != lpdis->itemID )
  182. {
  183. SpGetDescription( GetODComboBoxToken( lpdis->hwndItem, lpdis->itemID ), &dstrName );
  184. }
  185. else
  186. {
  187. dstrName = L"";
  188. }
  189. int cStringLen = wcslen( dstrName );
  190. SetTextAlign(lpdis->hDC, TA_UPDATECP);
  191. MoveToEx(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, NULL);
  192. ExtTextOutW(lpdis->hDC,
  193. lpdis->rcItem.left, lpdis->rcItem.top,
  194. options,
  195. &lpdis->rcItem,
  196. dstrName,
  197. cStringLen,
  198. NULL);
  199. ::SetTextColor( lpdis->hDC, clrfTextOld );
  200. ::SetBkColor( lpdis->hDC, clrfBkOld );
  201. SetTextAlign(lpdis->hDC, oldTextAlign);
  202. }