00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "CoolInterface.h"
00025 #include "CoolMenu.h"
00026 #include "Skin.h"
00027
00028 #ifdef _DEBUG
00029 #undef THIS_FILE
00030 static char THIS_FILE[]=__FILE__;
00031 #define new DEBUG_NEW
00032 #endif
00033
00034 #define CM_DISABLEDBLEND ILD_BLEND25
00035 #define CM_ICONWIDTH 16
00036 #define CM_ICONHEIGHT 16
00037
00038 CCoolMenu CoolMenu;
00039
00040
00042
00043
00044 CCoolMenu::CCoolMenu()
00045 {
00046 m_nCheckIcon = 0;
00047 m_bEnable = TRUE;
00048 m_bUnhook = FALSE;
00049 }
00050
00051 CCoolMenu::~CCoolMenu()
00052 {
00053 SetWatermark( NULL );
00054 if ( m_bUnhook ) EnableHook( FALSE );
00055 }
00056
00058
00059
00060 BOOL CCoolMenu::IsModernVersion()
00061 {
00062 OSVERSIONINFO pVersion;
00063 pVersion.dwOSVersionInfoSize = sizeof(pVersion);
00064 GetVersionEx( &pVersion );
00065
00066 return theApp.GetProfileInt( _T(""), _T("CoolMenuEnable"), TRUE ) &&
00067 ( pVersion.dwMajorVersion >= 5 ||
00068 ( pVersion.dwMajorVersion == 4 && pVersion.dwMinorVersion >= 10 ) );
00069 }
00070
00072
00073
00074 BOOL CCoolMenu::AddMenu(CMenu* pMenu, BOOL bChild)
00075 {
00076 if ( ! m_bEnable ) return FALSE;
00077
00078 for ( int i = 0 ; i < (int)pMenu->GetMenuItemCount() ; i++ )
00079 {
00080 TCHAR szBuffer[128];
00081 MENUITEMINFO mii;
00082
00083 ZeroMemory( &mii, sizeof(mii) );
00084 mii.cbSize = sizeof(mii);
00085 mii.fMask = MIIM_DATA|MIIM_ID|MIIM_TYPE|MIIM_SUBMENU;
00086 mii.dwTypeData = szBuffer;
00087 mii.cch = 128;
00088
00089 GetMenuItemInfo( pMenu->GetSafeHmenu(), i, MF_BYPOSITION, &mii );
00090
00091 if ( mii.fType & (MF_OWNERDRAW|MF_SEPARATOR) )
00092 {
00093 mii.fType |= MF_OWNERDRAW;
00094 if ( mii.fType & MF_SEPARATOR ) mii.dwItemData = 0;
00095 SetMenuItemInfo( pMenu->GetSafeHmenu(), i, MF_BYPOSITION, &mii );
00096 continue;
00097 }
00098
00099 mii.fType |= MF_OWNERDRAW;
00100 mii.dwItemData = ( (DWORD)pMenu->GetSafeHmenu() << 16 ) | ( mii.wID & 0xFFFF );
00101
00102 CString strText = szBuffer;
00103 m_pStrings.SetAt( mii.dwItemData, strText );
00104
00105 if ( bChild ) SetMenuItemInfo( pMenu->GetSafeHmenu(), i, MF_BYPOSITION, &mii );
00106
00107 if ( mii.hSubMenu != NULL ) AddMenu( pMenu->GetSubMenu( i ), TRUE );
00108 }
00109
00110 return TRUE;
00111 }
00112
00114
00115
00116 void CCoolMenu::SetWatermark(HBITMAP hBitmap)
00117 {
00118 if ( m_bmWatermark.m_hObject != NULL )
00119 {
00120 m_dcWatermark.SelectObject( CBitmap::FromHandle( m_hOldMark ) );
00121 m_bmWatermark.DeleteObject();
00122 m_dcWatermark.DeleteDC();
00123 }
00124
00125 if ( hBitmap != NULL )
00126 {
00127 CDC dc;
00128 dc.Attach( GetDC( 0 ) );
00129 if ( theApp.m_bRTL ) theApp.m_pfnSetLayout( dc.m_hDC, LAYOUT_BITMAPORIENTATIONPRESERVED );
00130 m_dcWatermark.CreateCompatibleDC( &dc );
00131 ReleaseDC( 0, dc.Detach() );
00132
00133 m_bmWatermark.Attach( hBitmap );
00134 m_hOldMark = (HBITMAP)m_dcWatermark.SelectObject( &m_bmWatermark )->GetSafeHandle();
00135
00136 BITMAP pInfo;
00137 m_bmWatermark.GetBitmap( &pInfo );
00138 m_czWatermark.cx = pInfo.bmWidth;
00139 m_czWatermark.cy = pInfo.bmHeight;
00140 }
00141 }
00142
00144
00145
00146 void CCoolMenu::OnMeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
00147 {
00148 if ( lpMeasureItemStruct->itemID == ID_SEPARATOR )
00149 {
00150 lpMeasureItemStruct->itemWidth = 16;
00151 lpMeasureItemStruct->itemHeight = 2;
00152 }
00153 else
00154 {
00155 CString strText;
00156 CDC dc;
00157
00158 m_pStrings.Lookup( lpMeasureItemStruct->itemData, strText );
00159
00160 dc.Attach( GetDC( 0 ) );
00161
00162 CFont* pOld = (CFont*)dc.SelectObject( &CoolInterface.m_fntNormal );
00163 CSize sz = dc.GetTextExtent( strText );
00164 dc.SelectObject( pOld );
00165
00166 ReleaseDC( 0, dc.Detach() );
00167
00168 lpMeasureItemStruct->itemWidth = sz.cx + 32;
00169 lpMeasureItemStruct->itemHeight = 23;
00170 }
00171
00172 if ( m_hMsgHook == NULL ) lpMeasureItemStruct->itemHeight ++;
00173 }
00174
00176
00177
00178 void CCoolMenu::OnDrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
00179 {
00180 CRect rcItem, rcText;
00181 CString strText;
00182 int nIcon = -1;
00183 CDC dc;
00184
00185 BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
00186 BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED;
00187 BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED;
00188 BOOL bKeyboard = FALSE;
00189 BOOL bEdge = TRUE;
00190
00191 dc.Attach( lpDrawItemStruct->hDC );
00192
00193 if ( CWnd* pWnd = dc.GetWindow() )
00194 {
00195 CRect rcScreen( &lpDrawItemStruct->rcItem );
00196 CPoint ptCursor;
00197
00198 GetCursorPos( &ptCursor );
00199 pWnd->ClientToScreen( &rcScreen );
00200
00201 bKeyboard = ! rcScreen.PtInRect( ptCursor );
00202 }
00203
00204 rcItem.CopyRect( &lpDrawItemStruct->rcItem );
00205 rcItem.OffsetRect( -rcItem.left, -rcItem.top );
00206 if ( m_hMsgHook != NULL ) rcItem.bottom += ( bEdge = m_bPrinted );
00207
00208 rcText.CopyRect( &rcItem );
00209 rcText.left += 32;
00210 rcText.right -= 2;
00211
00212 CDC* pDC = CoolInterface.GetBuffer( dc, rcItem.Size() );
00213
00214 if ( m_bmWatermark.m_hObject != NULL )
00215 {
00216 DrawWatermark( pDC, &rcItem, lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top );
00217 }
00218 else
00219 {
00220 pDC->FillSolidRect( rcItem.left, rcItem.top, 24, rcItem.Height(), CoolInterface.m_crMargin );
00221 pDC->FillSolidRect( rcItem.left + 24, rcItem.top, rcItem.Width() - 24, rcItem.Height(), CoolInterface.m_crBackNormal );
00222 }
00223
00224 if ( m_pStrings.Lookup( lpDrawItemStruct->itemData, strText ) == FALSE )
00225 {
00226 int nMiddle = rcText.top + 1;
00227
00228 pDC->FillSolidRect( rcText.left, nMiddle, rcText.Width() + 2, 1, CoolInterface.m_crDisabled );
00229
00230 dc.BitBlt( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top,
00231 rcItem.Width(), rcItem.Height(), pDC, 0, 0, SRCCOPY );
00232 dc.Detach();
00233
00234 return;
00235 }
00236
00237 if ( bSelected )
00238 {
00239 if ( ! bDisabled )
00240 {
00241 pDC->Draw3dRect( rcItem.left + 1, rcItem.top + 1,
00242 rcItem.Width() - 2, rcItem.Height() - 1 - bEdge,
00243 CoolInterface.m_crBorder, CoolInterface.m_crBorder );
00244 pDC->FillSolidRect( rcItem.left + 2, rcItem.top + 2,
00245 rcItem.Width() - 4, rcItem.Height() - 3 - bEdge,
00246 CoolInterface.m_crBackSel );
00247
00248 pDC->SetBkColor( CoolInterface.m_crBackSel );
00249 }
00250 else if ( bKeyboard )
00251 {
00252 pDC->Draw3dRect( rcItem.left + 1, rcItem.top + 1,
00253 rcItem.Width() - 2, rcItem.Height() - 1 - bEdge,
00254 CoolInterface.m_crBorder, CoolInterface.m_crBorder );
00255 pDC->FillSolidRect( rcItem.left + 2, rcItem.top + 2,
00256 rcItem.Width() - 4, rcItem.Height() - 3 - bEdge,
00257 CoolInterface.m_crBackNormal );
00258
00259 pDC->SetBkColor( CoolInterface.m_crBackNormal );
00260 }
00261 }
00262 else
00263 {
00264 pDC->SetBkColor( CoolInterface.m_crBackNormal );
00265 }
00266
00267 if ( bChecked )
00268 {
00269 pDC->Draw3dRect( rcItem.left + 2, rcItem.top + 2, 20, rcItem.Height() - 3 - bEdge,
00270 CoolInterface.m_crBorder, CoolInterface.m_crBorder );
00271 pDC->FillSolidRect( rcItem.left + 3, rcItem.top + 3, 18, rcItem.Height() - 5 - bEdge,
00272 ( bSelected && !bDisabled ) ? CoolInterface.m_crBackCheckSel : CoolInterface.m_crBackCheck );
00273 }
00274
00275 nIcon = CoolInterface.ImageForID( (DWORD)lpDrawItemStruct->itemID );
00276
00277 if ( bChecked && nIcon < 0 ) nIcon = m_nCheckIcon;
00278
00279 if ( nIcon >= 0 )
00280 {
00281 CPoint pt( rcItem.left + 4, rcItem.top + 4 );
00282
00283 if ( bDisabled )
00284 {
00285 ImageList_DrawEx( CoolInterface.m_pImages.m_hImageList, nIcon, pDC->GetSafeHdc(),
00286 pt.x, pt.y, 0, 0, CLR_NONE, CoolInterface.m_crDisabled, CM_DISABLEDBLEND );
00287 }
00288 else if ( bChecked )
00289 {
00290 CoolInterface.m_pImages.Draw( pDC, nIcon, pt, ILD_NORMAL );
00291 }
00292 else if ( bSelected )
00293 {
00294 pt.Offset( 1, 1 );
00295 pDC->SetTextColor( CoolInterface.m_crShadow );
00296 CoolInterface.m_pImages.Draw( pDC, nIcon, pt, ILD_MASK );
00297 pt.Offset( -2, -2 );
00298 CoolInterface.m_pImages.Draw( pDC, nIcon, pt, ILD_NORMAL );
00299 }
00300 else
00301 {
00302 ImageList_DrawEx( CoolInterface.m_pImages.m_hImageList, nIcon, pDC->GetSafeHdc(),
00303 pt.x, pt.y, 0, 0, CLR_NONE, CoolInterface.m_crMargin, ILD_BLEND25 );
00304 }
00305 }
00306
00307 CFont* pOld = (CFont*)pDC->SelectObject(
00308 ( lpDrawItemStruct->itemState & ODS_DEFAULT ) && ! bDisabled ?
00309 &CoolInterface.m_fntBold : &CoolInterface.m_fntNormal );
00310
00311 pDC->SetBkMode( TRANSPARENT );
00312 pDC->SetTextColor( bDisabled ? CoolInterface.m_crDisabled :
00313 ( bSelected ? CoolInterface.m_crCmdTextSel : CoolInterface.m_crCmdText ) );
00314 DrawMenuText( pDC, &rcText, strText );
00315
00316 pDC->SelectObject( pOld );
00317
00318 dc.BitBlt( lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top,
00319 rcItem.Width(), rcItem.Height(), pDC, 0, 0, SRCCOPY );
00320 dc.Detach();
00321 }
00322
00324
00325
00326 void CCoolMenu::DrawMenuText(CDC* pDC, CRect* pRect, const CString& strText)
00327 {
00328 theApp.m_bMenuWasVisible = TRUE;
00329 int nPos = strText.Find( '\t' );
00330
00331 if ( nPos >= 0 )
00332 {
00333 pRect->right -= 8;
00334 pDC->DrawText( strText.Left( nPos ), pRect, DT_SINGLELINE|DT_VCENTER|DT_LEFT );
00335 pDC->DrawText( strText.Mid( nPos + 1 ), pRect, DT_SINGLELINE|DT_VCENTER|DT_RIGHT );
00336 pRect->right += 8;
00337 }
00338 else
00339 {
00340 pDC->DrawText( strText, pRect, DT_SINGLELINE|DT_VCENTER|DT_LEFT );
00341 }
00342 }
00343
00345
00346
00347 void CCoolMenu::DrawWatermark(CDC* pDC, CRect* pRect, int nOffX, int nOffY)
00348 {
00349 for ( int nY = pRect->top - nOffY ; nY < pRect->bottom ; nY += m_czWatermark.cy )
00350 {
00351 if ( nY + m_czWatermark.cy < pRect->top ) continue;
00352
00353 for ( int nX = pRect->left - nOffX ; nX < pRect->right ; nX += m_czWatermark.cx )
00354 {
00355 if ( nX + m_czWatermark.cx < pRect->left ) continue;
00356
00357 pDC->BitBlt( nX, nY, m_czWatermark.cx, m_czWatermark.cy, &m_dcWatermark, 0, 0, SRCCOPY );
00358 }
00359 }
00360 }
00361
00363
00364
00365 HHOOK CCoolMenu::m_hMsgHook = NULL;
00366 LPCTSTR CCoolMenu::wpnOldProc = _T("RAZA_MenuOldWndProc");
00367 BOOL CCoolMenu::m_bPrinted = TRUE;
00368 int CCoolMenu::m_nEdgeLeft = 0;
00369 int CCoolMenu::m_nEdgeTop = 0;
00370 int CCoolMenu::m_nEdgeSize = 0;
00371
00372 void CCoolMenu::EnableHook()
00373 {
00374 ASSERT( m_hMsgHook == NULL );
00375 ASSERT( m_bUnhook == FALSE );
00376
00377 m_bEnable = IsModernVersion();
00378 if ( ! m_bEnable ) return;
00379
00380 m_bUnhook = TRUE;
00381 EnableHook( TRUE );
00382 }
00383
00384 void CCoolMenu::EnableHook(BOOL bEnable)
00385 {
00386 if ( bEnable == ( m_hMsgHook != NULL ) ) return;
00387
00388 if ( bEnable )
00389 {
00390 m_hMsgHook = SetWindowsHookEx( WH_CALLWNDPROC, MsgHook,
00391 AfxGetInstanceHandle(), GetCurrentThreadId() );
00392 }
00393 else
00394 {
00395 UnhookWindowsHookEx( m_hMsgHook );
00396 m_hMsgHook = NULL;
00397 }
00398 }
00399
00400 void CCoolMenu::RegisterEdge(int nLeft, int nTop, int nLength)
00401 {
00402 m_nEdgeLeft = nLeft;
00403 m_nEdgeTop = nTop;
00404 m_nEdgeSize = nLength;
00405 }
00406
00408
00409
00410 LRESULT CALLBACK CCoolMenu::MsgHook(int nCode, WPARAM wParam, LPARAM lParam)
00411 {
00412 CWPSTRUCT* pCWP = (CWPSTRUCT*)lParam;
00413
00414 while ( nCode == HC_ACTION )
00415 {
00416 if ( pCWP->message != WM_CREATE && pCWP->message != 0x01E2 ) break;
00417
00418 TCHAR szClassName[16];
00419 int nClassName = GetClassName( pCWP->hwnd, szClassName, 16 );
00420 if ( nClassName != 6 || _tcscmp( szClassName, _T("#32768") ) != 0 ) break;
00421
00422 if ( ::GetProp( pCWP->hwnd, wpnOldProc ) != NULL ) break;
00423
00424 HWND hWndFore = GetForegroundWindow();
00425 if ( hWndFore != NULL && CWnd::FromHandlePermanent( hWndFore ) == NULL ) break;
00426
00427 WNDPROC pWndProc = (WNDPROC)(LONG_PTR)::GetWindowLong( pCWP->hwnd, GWL_WNDPROC );
00428 if ( pWndProc == NULL ) break;
00429 ASSERT( pWndProc != MenuProc );
00430
00431 if ( ! SetProp( pCWP->hwnd, wpnOldProc, pWndProc ) ) break;
00432
00433 if ( ! SetWindowLong( pCWP->hwnd, GWL_WNDPROC, (DWORD)(DWORD_PTR)MenuProc ) )
00434 {
00435 ::RemoveProp( pCWP->hwnd, wpnOldProc );
00436 break;
00437 }
00438
00439 break;
00440 }
00441
00442 return CallNextHookEx( CCoolMenu::m_hMsgHook, nCode, wParam, lParam );
00443 }
00444
00445 LRESULT CALLBACK CCoolMenu::MenuProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00446 {
00447 WNDPROC pWndProc = (WNDPROC)::GetProp( hWnd, wpnOldProc );
00448
00449 switch ( uMsg )
00450 {
00451 case WM_NCCALCSIZE:
00452 {
00453 NCCALCSIZE_PARAMS* pCalc = (NCCALCSIZE_PARAMS*)lParam;
00454 pCalc->rgrc[0].left ++;
00455 pCalc->rgrc[0].top ++;
00456 pCalc->rgrc[0].right --;
00457 pCalc->rgrc[0].bottom --;
00458 }
00459 return 0;
00460
00461 case WM_WINDOWPOSCHANGING:
00462 if ( WINDOWPOS* pWndPos = (WINDOWPOS*)lParam )
00463 {
00464 DWORD nStyle = GetWindowLong( hWnd, GWL_STYLE );
00465 DWORD nExStyle = GetWindowLong( hWnd, GWL_EXSTYLE );
00466 CRect rc( 0, 0, 32, 32 );
00467
00468 AdjustWindowRectEx( &rc, nStyle, FALSE, nExStyle );
00469
00470 pWndPos->cx -= ( rc.Width() - 34 );
00471 pWndPos->cy -= ( rc.Height() - 34 ) - 1;
00472
00473 if ( pWndPos->x != m_nEdgeLeft || pWndPos->y != m_nEdgeTop )
00474 pWndPos->x ++;
00475 }
00476 break;
00477
00478 case WM_PRINT:
00479 if ( ( lParam & PRF_CHECKVISIBLE ) && ! IsWindowVisible( hWnd ) ) return 0;
00480 if ( lParam & PRF_NONCLIENT )
00481 {
00482 CWnd* pWnd = CWnd::FromHandle( hWnd );
00483 CDC* pDC = CDC::FromHandle( (HDC)wParam );
00484 CRect rc;
00485
00486 pWnd->GetWindowRect( &rc );
00487 BOOL bEdge = ( rc.left == m_nEdgeLeft && rc.top == m_nEdgeTop );
00488 rc.OffsetRect( -rc.left, -rc.top );
00489
00490 pDC->Draw3dRect( &rc, CoolInterface.m_crDisabled, CoolInterface.m_crDisabled );
00491 if ( bEdge ) pDC->FillSolidRect( rc.left + 1, rc.top, min( rc.Width(), m_nEdgeSize ) - 2, 1, CoolInterface.m_crBackNormal );
00492 }
00493 if ( lParam & PRF_CLIENT )
00494 {
00495 CWnd* pWnd = CWnd::FromHandle( hWnd );
00496 CDC* pDC = CDC::FromHandle( (HDC)wParam );
00497 CBitmap bmBuf, *pbmOld;
00498 CDC dcBuf;
00499 CRect rc;
00500
00501 pWnd->GetClientRect( &rc );
00502 dcBuf.CreateCompatibleDC( pDC );
00503 bmBuf.CreateCompatibleBitmap( pDC, rc.Width(), rc.Height() );
00504 pbmOld = (CBitmap*)dcBuf.SelectObject( &bmBuf );
00505
00506 m_bPrinted = TRUE;
00507 dcBuf.FillSolidRect( &rc, GetSysColor( COLOR_MENU ) );
00508 SendMessage( hWnd, WM_PRINTCLIENT, (WPARAM)dcBuf.GetSafeHdc(), 0 );
00509
00510 pDC->BitBlt( 1, 1, rc.Width(), rc.Height(), &dcBuf, 0, 0, SRCCOPY );
00511 dcBuf.SelectObject( pbmOld );
00512 }
00513 return 0;
00514
00515 case WM_NCPAINT:
00516 {
00517 CWnd* pWnd = CWnd::FromHandle( hWnd );
00518 CWindowDC dc( pWnd );
00519 CRect rc;
00520
00521 pWnd->GetWindowRect( &rc );
00522 BOOL bEdge = ( rc.left == m_nEdgeLeft && rc.top == m_nEdgeTop );
00523 rc.OffsetRect( -rc.left, -rc.top );
00524
00525 dc.Draw3dRect( &rc, CoolInterface.m_crDisabled, CoolInterface.m_crDisabled );
00526 if ( bEdge ) dc.FillSolidRect( rc.left + 1, rc.top, min( rc.Width(), m_nEdgeSize ) - 2, 1, CoolInterface.m_crBackNormal );
00527 }
00528 return 0;
00529
00530 case WM_PAINT:
00531 m_bPrinted = FALSE;
00532 break;
00533
00534 case WM_NCDESTROY:
00535 ::RemoveProp( hWnd, wpnOldProc );
00536 break;
00537 }
00538
00539 return CallWindowProc( pWndProc, hWnd, uMsg, wParam, lParam );
00540 }