SPDrawHelpers.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. #include "stdafx.h"
  2. #include "SPColorManager.h"
  3. #include "SPDrawHelpers.h"
  4. #ifdef _DEBUG
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #define new DEBUG_NEW
  8. #endif
  9. HHOOK CSPMouseMonitor::m_hHookMouse = 0;
  10. CWnd * CSPMouseMonitor::m_pWndMonitor = 0;
  11. //////////////////////////////////////////////////////////////////////////
  12. // CSPMouseMonitor
  13. //////////////////////////////////////////////////////////////////////////
  14. void CSPMouseMonitor::SetupHook( CWnd * pWndMonitor )
  15. {
  16. if ( pWndMonitor && m_hHookMouse == 0 )
  17. {
  18. m_hHookMouse = SetWindowsHookEx( WH_MOUSE,MouseProc,0,GetCurrentThreadId() );
  19. }
  20. if ( !pWndMonitor && m_hHookMouse )
  21. {
  22. UnhookWindowsHookEx( m_hHookMouse );
  23. m_hHookMouse = 0;
  24. }
  25. m_pWndMonitor = pWndMonitor;
  26. }
  27. LRESULT CALLBACK CSPMouseMonitor::MouseProc( int nCode , WPARAM wParam , LPARAM lParam )
  28. {
  29. if ( nCode != HC_ACTION || !m_pWndMonitor )
  30. {
  31. return CallNextHookEx( m_hHookMouse,nCode,wParam,lParam );
  32. }
  33. CSPWindowRect rc ( m_pWndMonitor );
  34. if ( !rc.PtInRect( ( ( PMOUSEHOOKSTRUCT ) lParam )->pt ) )
  35. {
  36. switch ( wParam )
  37. {
  38. case WM_LBUTTONDOWN:
  39. case WM_NCLBUTTONDOWN:
  40. case WM_RBUTTONDOWN:
  41. case WM_NCRBUTTONDOWN:
  42. case WM_MBUTTONDOWN:
  43. case WM_NCMBUTTONDOWN:
  44. case WM_LBUTTONUP:
  45. case WM_NCLBUTTONUP:
  46. m_pWndMonitor->GetOwner()->SetFocus();
  47. return TRUE;
  48. }
  49. }
  50. return CallNextHookEx( m_hHookMouse,nCode,wParam,lParam );
  51. }
  52. //===========================================================================
  53. // CSPClientCursorPos class
  54. //===========================================================================
  55. CSPTransparentBitmap::CSPTransparentBitmap( HBITMAP hBitmap ) : m_hBitmap( hBitmap )
  56. {
  57. }
  58. // Not foolproof, but works 99% of the time :). Assumes the top
  59. // left pixel is the transparent color.
  60. COLORREF CSPTransparentBitmap::GetTransparentColor() const
  61. {
  62. CBitmap * pBitmap = CBitmap::FromHandle( m_hBitmap );
  63. if ( pBitmap != NULL )
  64. {
  65. CSPCompatibleDC dc ( NULL,pBitmap );
  66. return dc.GetPixel( 0,0 );
  67. }
  68. return ( COLORREF ) - 1;
  69. }
  70. HICON CSPTransparentBitmap::ConvertToIcon() const
  71. {
  72. if ( m_hBitmap == NULL )
  73. {
  74. return NULL;
  75. }
  76. COLORREF crTransparent = GetTransparentColor();
  77. BITMAP bmp;
  78. if ( !::GetObject( m_hBitmap,sizeof( BITMAP ),&bmp ) )
  79. {
  80. return NULL;
  81. }
  82. if ( bmp.bmHeight == 0 || bmp.bmWidth == 0 )
  83. {
  84. return NULL;
  85. }
  86. CImageList il;
  87. il.Create( bmp.bmWidth,bmp.bmHeight,ILC_COLOR24 | ILC_MASK,0,1 );
  88. il.Add( CBitmap::FromHandle( m_hBitmap ),crTransparent );
  89. ASSERT( il.GetImageCount() == 1 );
  90. return il.ExtractIcon( 0 );
  91. }
  92. //===========================================================================
  93. // CSPClientCursorPos class
  94. //===========================================================================
  95. CSPClientCursorPos::CSPClientCursorPos( CWnd * pWnd )
  96. {
  97. GetCursorPos( this );
  98. pWnd->ScreenToClient( this );
  99. }
  100. //===========================================================================
  101. // CSPEmptyRect class
  102. //===========================================================================
  103. CSPEmptyRect::CSPEmptyRect()
  104. {
  105. SetRectEmpty();
  106. }
  107. //===========================================================================
  108. // CSPWindowRect class
  109. //===========================================================================
  110. CSPWindowRect::CSPWindowRect( HWND hWnd )
  111. {
  112. if ( ::IsWindow( hWnd ) )
  113. {
  114. ::GetWindowRect( hWnd,this );
  115. }
  116. else
  117. {
  118. SetRectEmpty();
  119. }
  120. }
  121. CSPWindowRect::CSPWindowRect( const CWnd * pWnd )
  122. {
  123. if ( ::IsWindow( pWnd->GetSafeHwnd() ) )
  124. {
  125. ::GetWindowRect( pWnd->GetSafeHwnd(),this );
  126. }
  127. else
  128. {
  129. SetRectEmpty();
  130. }
  131. }
  132. //===========================================================================
  133. // CSPClientRect class
  134. //===========================================================================
  135. CSPClientRect::CSPClientRect( HWND hWnd )
  136. {
  137. if ( ::IsWindow( hWnd ) )
  138. {
  139. ::GetClientRect( hWnd,this );
  140. }
  141. else
  142. {
  143. SetRectEmpty();
  144. }
  145. }
  146. CSPClientRect::CSPClientRect( const CWnd * pWnd )
  147. {
  148. if ( ::IsWindow( pWnd->GetSafeHwnd() ) )
  149. {
  150. ::GetClientRect( pWnd->GetSafeHwnd(),this );
  151. }
  152. else
  153. {
  154. SetRectEmpty();
  155. }
  156. }
  157. //===========================================================================
  158. // CSPBufferDC class
  159. //===========================================================================
  160. CSPBufferDC::CSPBufferDC( HDC hDestDC , const CRect rcPaint ) : m_hDestDC( hDestDC )
  161. {
  162. m_rect = rcPaint;
  163. Attach( ::CreateCompatibleDC( m_hDestDC ) );
  164. m_bitmap.Attach( ::CreateCompatibleBitmap( m_hDestDC,m_rect.right,m_rect.bottom ) );
  165. m_hOldBitmap = ::SelectObject( m_hDC,m_bitmap );
  166. }
  167. CSPBufferDC::~CSPBufferDC()
  168. {
  169. ::BitBlt( m_hDestDC,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height(),m_hDC,m_rect.left,m_rect.top,SRCCOPY );
  170. ::SelectObject( m_hDC,m_hOldBitmap );
  171. }
  172. CDC * CSPBufferDC::GetDestDC()
  173. {
  174. return CDC::FromHandle( m_hDestDC );
  175. }
  176. //===========================================================================
  177. // CSPFontDC class
  178. //===========================================================================
  179. CSPFontDC::CSPFontDC( CDC * pDC , CFont * pFont ) : m_hDC( pDC->GetSafeHdc() )
  180. {
  181. m_hOldFont = SelectObject( m_hDC,pFont->GetSafeHandle() );
  182. }
  183. CSPFontDC::~CSPFontDC()
  184. {
  185. ::SelectObject( m_hDC,m_hOldFont );
  186. }
  187. void CSPFontDC::SetFont( CFont * pFont )
  188. {
  189. ::SelectObject( m_hDC,m_hOldFont );
  190. m_hOldFont = SelectObject( m_hDC,pFont->GetSafeHandle() );
  191. }
  192. //===========================================================================
  193. // CSPPenDC class
  194. //===========================================================================
  195. CSPPenDC::CSPPenDC( HDC hDC , COLORREF crColor ) : m_hDC( hDC )
  196. {
  197. VERIFY( m_pen.CreatePen( PS_SOLID,1,crColor ) );
  198. m_hOldPen = ( HPEN ) ::SelectObject( m_hDC,m_pen );
  199. }
  200. CSPPenDC::~CSPPenDC()
  201. {
  202. ::SelectObject( m_hDC,m_hOldPen );
  203. }
  204. void CSPPenDC::Color( COLORREF crColor )
  205. {
  206. ::SelectObject( m_hDC,m_hOldPen );
  207. VERIFY( m_pen.DeleteObject() );
  208. VERIFY( m_pen.CreatePen( PS_SOLID,1,crColor ) );
  209. m_hOldPen = ( HPEN ) ::SelectObject( m_hDC,m_pen );
  210. }
  211. COLORREF CSPPenDC::Color()
  212. {
  213. LOGPEN logPen;
  214. m_pen.GetLogPen( &logPen );
  215. return logPen.lopnColor;
  216. }
  217. //===========================================================================
  218. // CSPBrushDC class
  219. //===========================================================================
  220. CSPBrushDC::CSPBrushDC( HDC hDC , COLORREF crColor ) : m_hDC( hDC )
  221. {
  222. VERIFY( m_brush.CreateSolidBrush( crColor ) );
  223. m_hOldBrush = ( HBRUSH ) ::SelectObject( m_hDC,m_brush );
  224. }
  225. CSPBrushDC::~CSPBrushDC()
  226. {
  227. ::SelectObject( m_hDC,m_hOldBrush );
  228. }
  229. void CSPBrushDC::Color( COLORREF crColor )
  230. {
  231. ::SelectObject( m_hDC,m_hOldBrush );
  232. VERIFY( m_brush.DeleteObject() );
  233. VERIFY( m_brush.CreateSolidBrush( crColor ) );
  234. m_hOldBrush = ( HBRUSH ) ::SelectObject( m_hDC,m_brush );
  235. }
  236. //===========================================================================
  237. // CSPCompatibleDC class
  238. //===========================================================================
  239. CSPCompatibleDC::CSPCompatibleDC( CDC * pDC , CBitmap * pBitmap )
  240. {
  241. CreateCompatibleDC( pDC );
  242. m_pBmp = SelectObject( pBitmap );
  243. }
  244. CSPCompatibleDC::~CSPCompatibleDC()
  245. {
  246. SelectObject( m_pBmp );
  247. DeleteDC();
  248. }
  249. //===========================================================================
  250. // CSPSplitterTracker class
  251. //===========================================================================
  252. CSPSplitterTracker::CSPSplitterTracker( BOOL bSolid /*= FALSE*/ )
  253. {
  254. m_bSolid = bSolid;
  255. m_rcBoundRect.SetRectEmpty();
  256. }
  257. void CSPSplitterTracker::OnInvertTracker( CRect rect )
  258. {
  259. ASSERT( !rect.IsRectEmpty() );
  260. if ( m_bSolid )
  261. {
  262. m_pDC->InvertRect( rect );
  263. }
  264. else
  265. {
  266. CBrush *pDitherBrush = CDC::GetHalftoneBrush();
  267. CBrush *pBrush = ( CBrush * ) m_pDC->SelectObject( pDitherBrush );
  268. m_pDC->PatBlt( rect.left,rect.top,rect.Width(),rect.Height(),PATINVERT );
  269. m_pDC->SelectObject( pBrush );
  270. }
  271. }
  272. BOOL CSPSplitterTracker::Track( CWnd * pTrackWnd , CRect rcAvail , CRect & rectTracker , CPoint point , BOOL bHoriz )
  273. {
  274. pTrackWnd->SetCapture();
  275. m_pDC = 0;
  276. CWnd * pWnd = CWnd::GetDesktopWindow();
  277. if ( pWnd->LockWindowUpdate() )
  278. {
  279. m_pDC = pWnd->GetDCEx( NULL,DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE );
  280. }
  281. else
  282. {
  283. m_pDC = pWnd->GetDCEx( NULL,DCX_WINDOW | DCX_CACHE );
  284. }
  285. ASSERT( m_pDC != NULL );
  286. CPoint ptOffset = bHoriz ? CPoint( rectTracker.left - point.x,0 ) : CPoint( 0,rectTracker.top - point.y );
  287. OnInvertTracker( rectTracker );
  288. if ( !m_rcBoundRect.IsRectEmpty() )
  289. {
  290. OnInvertTracker( m_rcBoundRect );
  291. }
  292. BOOL bAccept = FALSE;
  293. while ( CWnd::GetCapture() == pTrackWnd )
  294. {
  295. MSG msg;
  296. if ( !GetMessage( &msg,NULL,0,0 ) )
  297. break;
  298. if ( msg.message == WM_MOUSEMOVE )
  299. {
  300. point = CPoint( msg.lParam );
  301. pTrackWnd->ClientToScreen( &point );
  302. point += ptOffset;
  303. point.x = max( min( point.x,rcAvail.right ),rcAvail.left );
  304. point.y = max( min( point.y,rcAvail.bottom ),rcAvail.top );
  305. if ( bHoriz )
  306. {
  307. if ( rectTracker.left != point.x )
  308. {
  309. OnInvertTracker( rectTracker );
  310. rectTracker.OffsetRect( point.x - rectTracker.left,0 );
  311. OnInvertTracker( rectTracker );
  312. }
  313. }
  314. else
  315. {
  316. if ( rectTracker.top != point.y )
  317. {
  318. OnInvertTracker( rectTracker );
  319. rectTracker.OffsetRect( 0,point.y - rectTracker.top );
  320. OnInvertTracker( rectTracker );
  321. }
  322. }
  323. }
  324. else if ( msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE )
  325. break;
  326. else if ( msg.message == WM_LBUTTONUP )
  327. {
  328. bAccept = TRUE;
  329. break;
  330. }
  331. else
  332. ::DispatchMessage( &msg );
  333. }
  334. if ( !m_rcBoundRect.IsRectEmpty() )
  335. {
  336. OnInvertTracker( m_rcBoundRect );
  337. }
  338. OnInvertTracker( rectTracker );
  339. if ( CWnd::GetCapture() == pTrackWnd )
  340. {
  341. ReleaseCapture();
  342. }
  343. pWnd = CWnd::GetDesktopWindow();
  344. pWnd->UnlockWindowUpdate();
  345. if ( m_pDC != NULL )
  346. {
  347. pWnd->ReleaseDC( m_pDC );
  348. m_pDC = NULL;
  349. }
  350. return bAccept;
  351. }
  352. //===========================================================================
  353. // CSPDrawHelpers class
  354. //===========================================================================
  355. CSPDrawHelpers CSPDrawHelpers::m_instance; // singleton
  356. CSPDrawHelpers::CSPDrawHelpers() : m_hMsImgDll( NULL )
  357. {
  358. m_pfnFastGradientFill = 0;
  359. m_hMsImgDll = ::LoadLibrary( _T( "msimg32.dll" ) );
  360. if ( m_hMsImgDll )
  361. {
  362. m_pfnFastGradientFill = ( PFNGRADIENTFILL ) GetProcAddress( m_hMsImgDll,"GradientFill" );
  363. }
  364. }
  365. CSPDrawHelpers::~CSPDrawHelpers()
  366. {
  367. if ( m_hMsImgDll != NULL )
  368. {
  369. ::FreeLibrary( m_hMsImgDll );
  370. }
  371. }
  372. BOOL CSPDrawHelpers::GradientFill( HDC hdc , PTRIVERTEX pVertex , ULONG dwNumVertex , PVOID pMesh , ULONG dwNumMesh , ULONG dwMode )
  373. {
  374. if ( m_pfnFastGradientFill )
  375. {
  376. return ( *m_pfnFastGradientFill ) ( hdc,pVertex,dwNumVertex,pMesh,dwNumMesh,dwMode );
  377. }
  378. return FALSE;
  379. }
  380. void CSPDrawHelpers::GradientFillSlow( CDC * pDC , LPRECT lpRect , COLORREF crFrom , COLORREF crTo , BOOL bHorz )
  381. {
  382. int cx = max( 1,lpRect->right - lpRect->left );
  383. int cy = max( 1,lpRect->bottom - lpRect->top );
  384. CRect rc;
  385. pDC->GetClipBox( &rc );
  386. if ( rc.IsRectEmpty() )
  387. {
  388. rc = *lpRect;
  389. }
  390. else
  391. {
  392. rc.IntersectRect( rc,lpRect );
  393. }
  394. if ( bHorz )
  395. {
  396. for ( int nX = rc.left; nX < rc.right; nX++ )
  397. {
  398. pDC->FillSolidRect( nX,rc.top,1,rc.Height(),BlendColors( crFrom,crTo,( float ) ( 1.0 - ( ( nX - lpRect->left ) / ( float ) cx ) ) ) );
  399. }
  400. }
  401. else
  402. {
  403. for ( int nY = rc.top; nY < rc.bottom; nY++ )
  404. {
  405. pDC->FillSolidRect( rc.left,nY,rc.Width(),1,BlendColors( crFrom,crTo,( float ) ( 1.0 - ( ( nY - lpRect->top ) ) / ( float ) cy ) ) );
  406. }
  407. }
  408. }
  409. void CSPDrawHelpers::GradientFillFast( CDC * pDC , LPRECT lpRect , COLORREF crFrom , COLORREF crTo , BOOL bHorz )
  410. {
  411. TRIVERTEX vert[2];
  412. vert[0].x = lpRect->left;
  413. vert[0].y = lpRect->top;
  414. vert[0].Red = ( COLOR16 ) ( GetRValue( crFrom ) << 8 );
  415. vert[0].Green = ( COLOR16 ) ( GetGValue( crFrom ) << 8 );
  416. vert[0].Blue = ( COLOR16 ) ( GetBValue( crFrom ) << 8 );
  417. vert[0].Alpha = 0x0000;
  418. vert[1].x = lpRect->right;
  419. vert[1].y = lpRect->bottom;
  420. vert[1].Red = ( COLOR16 ) ( GetRValue( crTo ) << 8 );
  421. vert[1].Green = ( COLOR16 ) ( GetGValue( crTo ) << 8 );
  422. vert[1].Blue = ( COLOR16 ) ( GetBValue( crTo ) << 8 );
  423. vert[1].Alpha = 0x0000;
  424. GRADIENT_RECT gRect ={0, 1};
  425. GradientFill( *pDC,vert,2,&gRect,1,bHorz ? GRADIENT_FILL_RECT_H : GRADIENT_FILL_RECT_V );
  426. }
  427. void CSPDrawHelpers::GradientFill( CDC * pDC , LPRECT lpRect , COLORREF crFrom , COLORREF crTo , BOOL bHorz )
  428. {
  429. if ( !lpRect )
  430. {
  431. return;
  432. }
  433. if ( ::IsRectEmpty( lpRect ) )
  434. {
  435. return;
  436. }
  437. if ( IsLowResolution( pDC->GetSafeHdc() ) )
  438. {
  439. pDC->FillSolidRect( lpRect,crFrom );
  440. }
  441. else if ( crFrom == crTo )
  442. {
  443. pDC->FillSolidRect( lpRect,crFrom );
  444. }
  445. else if ( m_pfnFastGradientFill != NULL )
  446. {
  447. GradientFillFast( pDC,lpRect,crFrom,crTo,bHorz );
  448. }
  449. else
  450. {
  451. GradientFillSlow( pDC,lpRect,crFrom,crTo,bHorz );
  452. }
  453. }
  454. void CSPDrawHelpers::GradientFill( CDC * pDC , LPRECT lpRect , CSPPaintManagerColorGradient & grc , BOOL bHorz )
  455. {
  456. GradientFill( pDC,lpRect,grc.clrLight,grc.clrDark,bHorz );
  457. }
  458. void CSPDrawHelpers::ExcludeCorners( CDC * pDC , CRect rc )
  459. {
  460. pDC->ExcludeClipRect( rc.left,rc.top,rc.left + 1,rc.top + 1 );
  461. pDC->ExcludeClipRect( rc.right - 1,rc.top,rc.right,rc.top + 1 );
  462. pDC->ExcludeClipRect( rc.left,rc.bottom - 1,rc.left + 1,rc.bottom + 1 );
  463. pDC->ExcludeClipRect( rc.right - 1,rc.bottom - 1,rc.right,rc.bottom + 1 );
  464. }
  465. void CSPDrawHelpers::BlurPoints( CDC * pDC , LPPOINT pts , int nCount )
  466. {
  467. for ( int i = 0; i < nCount; i += 2 )
  468. {
  469. CPoint ptBlur = pts[i];
  470. CPoint ptDirection ( pts[i].x + pts[i + 1].x,pts[i].y + pts[i + 1].y );
  471. COLORREF clrBlur = pDC->GetPixel( ptDirection );
  472. COLORREF clrDirection = pDC->GetPixel( ptBlur );
  473. pDC->SetPixel( ptBlur,RGB( ( GetRValue( clrBlur ) + GetRValue( clrDirection ) ) / 2,( GetGValue( clrBlur ) + GetGValue( clrDirection ) ) / 2,( GetBValue( clrBlur ) + GetBValue( clrDirection ) ) / 2 ) );
  474. }
  475. }
  476. COLORREF CSPDrawHelpers::BlendColors( COLORREF crA , COLORREF crB , float fAmountA )
  477. {
  478. BYTE btR = ( BYTE ) min( 255,( int ) ( GetRValue( crA ) * fAmountA + GetRValue( crB ) * ( 1.0f - fAmountA ) ) );
  479. BYTE btG = ( BYTE ) min( 255,( int ) ( GetGValue( crA ) * fAmountA + GetGValue( crB ) * ( 1.0f - fAmountA ) ) );
  480. BYTE btB = ( BYTE ) min( 255,( int ) ( GetBValue( crA ) * fAmountA + GetBValue( crB ) * ( 1.0f - fAmountA ) ) );
  481. return RGB( btR,btG,btB );
  482. }
  483. static int CALLBACK SPEnumFontFamExProc( ENUMLOGFONTEX * pelf , NEWTEXTMETRICEX* /*lpntm*/ , int /*FontType*/ , LPVOID pThis )
  484. {
  485. CString strFontName = *( CString * ) pThis;
  486. CString strFaceName = pelf->elfLogFont.lfFaceName;
  487. if ( strFaceName.CompareNoCase( strFontName ) == 0 )
  488. {
  489. return 0;
  490. }
  491. return 1;
  492. }
  493. BOOL CSPDrawHelpers::FontExists( CString & strFaceName )
  494. {
  495. // Enumerate all styles and charsets of all fonts:
  496. LOGFONT lfEnum;
  497. ::ZeroMemory( &lfEnum,sizeof( LOGFONT ) );
  498. lfEnum.lfFaceName[0] = 0;
  499. lfEnum.lfCharSet = DEFAULT_CHARSET;
  500. CWindowDC dc ( NULL );
  501. return ::EnumFontFamiliesEx( dc.m_hDC,&lfEnum,( FONTENUMPROC ) SPEnumFontFamExProc,( LPARAM ) & strFaceName,0 ) == 0;
  502. }
  503. CString CSPDrawHelpers::GetDefaultFontName()
  504. {
  505. LOGFONT lfFont;
  506. ::GetObject( ::GetStockObject( DEFAULT_GUI_FONT ),sizeof( LOGFONT ),&lfFont );
  507. return CString( lfFont.lfFaceName );
  508. }
  509. CString CSPDrawHelpers::GetVerticalFontName( BOOL bUseOfficeFont )
  510. {
  511. LOGFONT lfFont;
  512. ::GetObject( ::GetStockObject( DEFAULT_GUI_FONT ),sizeof( LOGFONT ),&lfFont );
  513. bool bUseSystemFont = lfFont.lfCharSet > SYMBOL_CHARSET;
  514. if ( bUseSystemFont )
  515. {
  516. OSVERSIONINFO osvi;
  517. osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  518. VERIFY( GetVersionEx( &osvi ) );
  519. if ( !( ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT ) && ( osvi.dwMajorVersion > 4 ) ) )
  520. bUseSystemFont = FALSE;
  521. }
  522. CString strOfficeFont = _T( "Tahoma" );
  523. CString strVerticalFaceName = _T( "Arial" );
  524. if ( bUseSystemFont || !FontExists( strVerticalFaceName ) )
  525. {
  526. strVerticalFaceName = lfFont.lfFaceName;
  527. }
  528. else if ( bUseOfficeFont && !bUseSystemFont && FontExists( strOfficeFont ) )
  529. {
  530. strVerticalFaceName = strOfficeFont;
  531. }
  532. return strVerticalFaceName;
  533. }
  534. void CSPDrawHelpers::Triangle( CDC * pDC , CPoint pt0 , CPoint pt1 , CPoint pt2 , COLORREF clr )
  535. {
  536. CSPPenDC pen ( *pDC,clr );
  537. CSPBrushDC brush ( *pDC,clr );
  538. Triangle( pDC,pt0,pt1,pt2 );
  539. }
  540. BOOL CSPDrawHelpers::IsLowResolution( HDC hDC/* = 0*/ )
  541. {
  542. if ( hDC )
  543. {
  544. int nColors = ::GetDeviceCaps( hDC,BITSPIXEL );
  545. return ( nColors > 0 && nColors <= 8 );
  546. }
  547. hDC = ::GetDC( ::GetDesktopWindow() );
  548. if ( hDC )
  549. {
  550. int nColors = ::GetDeviceCaps( hDC,BITSPIXEL );
  551. ::ReleaseDC( ::GetDesktopWindow(),hDC );
  552. return ( nColors > 0 && nColors <= 8 );
  553. }
  554. return FALSE;
  555. }
  556. SPCurrentSystemTheme CSPDrawHelpers::GetCurrentSystemTheme()
  557. {
  558. return SPColorManager()->GetCurrentSystemTheme();
  559. }
  560. //=============================================================================
  561. // Multi-Monitor API
  562. //=============================================================================
  563. class CSPMultiMonitor
  564. {
  565. protected:
  566. DECLARE_HANDLE( HMONITOR );
  567. protected:
  568. typedef struct tagMONITORINFO
  569. {
  570. DWORD cbSize;
  571. RECT rcMonitor;
  572. RECT rcWork;
  573. DWORD dwFlags;
  574. } MONITORINFO, * LPMONITORINFO;
  575. protected:
  576. CSPMultiMonitor();
  577. protected:
  578. BOOL InitMultipleMonitorStubs();
  579. CRect GetWorkArea( HMONITOR hMonitor )
  580. {
  581. if ( hMonitor && m_pfnGetMonitorInfo )
  582. {
  583. ASSERT( sizeof( MONITORINFO ) == 40 );
  584. MONITORINFO info;
  585. info.cbSize = sizeof( MONITORINFO );
  586. if ( m_pfnGetMonitorInfo( hMonitor,( MONITORINFO * ) &info ) )
  587. return info.rcWork;
  588. }
  589. RECT rcWork;
  590. ::SystemParametersInfo( SPI_GETWORKAREA,NULL,&rcWork,0 );
  591. return rcWork;
  592. }
  593. public:
  594. CRect GetWorkArea( HWND hWnd )
  595. {
  596. return GetWorkArea( InitMultipleMonitorStubs() ? m_pfnMonitorFromWindow( hWnd,0 ) : 0 );
  597. }
  598. CRect GetWorkArea( POINT ptScreenCoords )
  599. {
  600. return GetWorkArea( InitMultipleMonitorStubs() ? m_pfnMonitorFromPoint( ptScreenCoords,0 ) : 0 );
  601. }
  602. CRect GetWorkArea( LPCRECT lprcScreenCoords )
  603. {
  604. return GetWorkArea( InitMultipleMonitorStubs() ? m_pfnMonitorFromRect( lprcScreenCoords,0 ) : 0 );
  605. }
  606. protected:
  607. int ( WINAPI* m_pfnGetSystemMetrics )( int );
  608. HMONITOR ( WINAPI* m_pfnMonitorFromWindow )( HWND , DWORD );
  609. HMONITOR ( WINAPI* m_pfnMonitorFromRect )( LPCRECT , DWORD );
  610. HMONITOR ( WINAPI* m_pfnMonitorFromPoint )( POINT , DWORD );
  611. BOOL ( WINAPI* m_pfnGetMonitorInfo )( HMONITOR , LPMONITORINFO );
  612. BOOL m_fMultiMonInitDone;
  613. public:
  614. static CSPMultiMonitor s_monInstance;
  615. };
  616. CSPMultiMonitor CSPMultiMonitor::s_monInstance;
  617. CSPMultiMonitor::CSPMultiMonitor()
  618. {
  619. m_fMultiMonInitDone = FALSE;
  620. }
  621. BOOL CSPMultiMonitor::InitMultipleMonitorStubs()
  622. {
  623. if ( m_fMultiMonInitDone )
  624. {
  625. return m_pfnGetMonitorInfo != NULL;
  626. }
  627. #ifdef UNICODE
  628. OSVERSIONINFO osvi ={0};
  629. osvi.dwOSVersionInfoSize = sizeof( osvi );
  630. GetVersionEx( &osvi );
  631. BOOL fMultimonPlatformNT = ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId );
  632. #endif
  633. HMODULE hUser32 = GetModuleHandle( TEXT( "USER32" ) );
  634. if ( hUser32 && ( *( FARPROC * ) &m_pfnGetSystemMetrics = GetProcAddress( hUser32,"GetSystemMetrics" ) ) != NULL && ( *( FARPROC * ) &m_pfnMonitorFromWindow = GetProcAddress( hUser32,"MonitorFromWindow" ) ) != NULL && ( *( FARPROC * ) &m_pfnMonitorFromRect = GetProcAddress( hUser32,"MonitorFromRect" ) ) != NULL && ( *( FARPROC * ) &m_pfnMonitorFromPoint = GetProcAddress( hUser32,"MonitorFromPoint" ) ) != NULL &&
  635. #ifdef UNICODE
  636. ( *( FARPROC * ) &m_pfnGetMonitorInfo = fMultimonPlatformNT ? GetProcAddress( hUser32,"GetMonitorInfoW" ) : GetProcAddress( hUser32,"GetMonitorInfoA" ) ) != NULL
  637. #else
  638. ( *( FARPROC * ) &m_pfnGetMonitorInfo = GetProcAddress( hUser32,"GetMonitorInfoA" ) ) != NULL
  639. #endif
  640. )
  641. {
  642. m_fMultiMonInitDone = TRUE;
  643. return TRUE;
  644. }
  645. else
  646. {
  647. m_pfnGetSystemMetrics = NULL;
  648. m_pfnMonitorFromWindow = NULL;
  649. m_pfnMonitorFromRect = NULL;
  650. m_pfnMonitorFromPoint = NULL;
  651. m_pfnGetMonitorInfo = NULL;
  652. m_fMultiMonInitDone = TRUE;
  653. return FALSE;
  654. }
  655. }
  656. CRect CSPDrawHelpers::GetWorkArea( const CRect & rect )
  657. {
  658. return CSPMultiMonitor::s_monInstance.GetWorkArea( rect );
  659. }
  660. CRect CSPDrawHelpers::GetWorkArea( const CWnd * pWnd )
  661. {
  662. ASSERT_VALID( pWnd );
  663. return CSPMultiMonitor::s_monInstance.GetWorkArea( pWnd->GetSafeHwnd() );
  664. }
  665. CRect CSPDrawHelpers::GetWorkArea()
  666. {
  667. POINT point;
  668. ::GetCursorPos( &point );
  669. return CSPMultiMonitor::s_monInstance.GetWorkArea( point );
  670. }