|
|
/*****************************************************************************\
FILE: PreviewTh.cpp
DESCRIPTION: This code will display a preview of the currently selected visual styles.
BryanSt 5/5/2000 Copyright (C) Microsoft Corp 2000-2000. All rights reserved. \*****************************************************************************/
#include "priv.h"
#include "PreviewTh.h"
#include "PreviewSM.h"
#include "classfactory.h"
// Old predef for Patterns
#define CXYDESKPATTERN 8
// Async Bitmap loading
#define PREVIEW_PICTURE_FILENAME TEXT("PrePict.htm")
#define WM_HTML_BITMAP (WM_USER + 100)
#define WM_ASYNC_BITMAP (WM_HTML_BITMAP + 1)
typedef struct{ HWND hwnd; HBITMAP hbmp; DWORD id; WCHAR szFile[MAX_PATH]; } ASYNCWALLPARAM, * PASYNCWALLPARAM;
// Window Class Name
#define THEMEPREV_CLASS TEXT("ThemePreview")
//===========================
// *** IThemePreview Interface ***
//===========================
extern LPCWSTR s_Icons[];
HRESULT CPreviewTheme::UpdatePreview(IN IPropertyBag * pPropertyBag) { HRESULT hr = E_INVALIDARG;
DEBUG_CODE(DebugStartWatch());
if (pPropertyBag && _hwndPrev) { SYSTEMMETRICSALL systemMetricsAll = {0}; hr = SHPropertyBag_ReadByRef(pPropertyBag, SZ_PBPROP_SYSTEM_METRICS, &systemMetricsAll, sizeof(systemMetricsAll)); BOOL fSysMetDirty = (memcmp(&systemMetricsAll, &_systemMetricsAll, sizeof(SYSTEMMETRICSALL)) != 0); if (fSysMetDirty) memcpy(&_systemMetricsAll, &systemMetricsAll, sizeof(_systemMetricsAll));
_putBackground(NULL, TRUE, 0);
if (_fShowBack) { WCHAR szBackgroundPath[MAX_PATH]; DWORD dwBackgroundTile;
// See the list of Property Bag names for Themes in shpriv.idl
hr = SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_BACKGROUND_PATH, szBackgroundPath, ARRAYSIZE(szBackgroundPath)); hr = SHPropertyBag_ReadDWORD(pPropertyBag, SZ_PBPROP_BACKGROUND_TILE, &dwBackgroundTile);
if ((lstrcmp(szBackgroundPath, _szBackgroundPath) != 0) || (_iTileMode != (int)dwBackgroundTile)) { StringCchCopy(_szBackgroundPath, ARRAYSIZE(_szBackgroundPath), szBackgroundPath); _putBackground(_szBackgroundPath, FALSE, dwBackgroundTile); } }
if (_fShowVS) { WCHAR szVSPath[MAX_PATH]; WCHAR szVSColor[MAX_PATH]; WCHAR szVSSize[MAX_PATH];
hr = SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_VISUALSTYLE_PATH, szVSPath, ARRAYSIZE(szVSPath)); hr = SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_VISUALSTYLE_COLOR, szVSColor, ARRAYSIZE(szVSColor)); hr = SHPropertyBag_ReadStr(pPropertyBag, SZ_PBPROP_VISUALSTYLE_SIZE, szVSSize, ARRAYSIZE(szVSSize));
if ((lstrcmp(szVSPath, _szVSPath) != 0) || (lstrcmp(szVSColor, _szVSColor) != 0) || (lstrcmp(szVSSize, _szVSSize) != 0) || fSysMetDirty) { StringCchCopy(_szVSPath, ARRAYSIZE(_szVSPath), szVSPath); StringCchCopy(_szVSColor, ARRAYSIZE(_szVSColor), szVSColor); StringCchCopy(_szVSSize, ARRAYSIZE(_szVSSize), szVSSize); _putVisualStyle(_szVSPath, _szVSColor, _szVSSize, &_systemMetricsAll); } }
if (_fShowIcons) { _putIcons(pPropertyBag); } }
DEBUG_CODE(TraceMsg(TF_THEMEUI_PERF, "CPreviewTheme::UpdatePreview() returned %#08lx. Time=%lums", hr, DebugStopWatch()));
return hr; }
HRESULT CPreviewTheme::CreatePreview(IN HWND hwndParent, IN DWORD dwFlags, IN DWORD dwStyle, IN DWORD dwExStyle, IN int x, IN int y, IN int nWidth, IN int nHeight, IN IPropertyBag * pPropertyBag, IN DWORD dwCtrlID) { HRESULT hr = S_OK;
DEBUG_CODE(DebugStartWatch());
g_bMirroredOS = IS_MIRRORING_ENABLED(); _fRTL = IS_WINDOW_RTL_MIRRORED(hwndParent); _hwndPrev = CreateWindowEx(dwExStyle, THEMEPREV_CLASS, L"Preview", dwStyle, x, y, nWidth, nHeight, hwndParent, (HMENU)IntToPtr(dwCtrlID), HINST_THISDLL, NULL); if (_hwndPrev) { SetWindowLongPtr(_hwndPrev, GWLP_USERDATA, (LONG_PTR)this); if (_pThumb) _pThumb->Init(_hwndPrev, WM_HTML_BITMAP);
GetClientRect(_hwndPrev, &_rcOuter);
if (dwFlags & TMPREV_SHOWMONITOR) { _fShowMon = TRUE;
BITMAP bmMon; GetObject(_hbmMon, sizeof(bmMon), &bmMon);
int ox = (RECTWIDTH(_rcOuter) - bmMon.bmWidth) / 2; int oy = (RECTHEIGHT(_rcOuter) - bmMon.bmHeight) / 2; RECT rc = { 16 + ox, 17 + oy, 168 + ox, 129 + oy}; _rcInner = rc; _cxMon = ox; _cyMon = oy; } else { _rcInner = _rcOuter; }
HDC hdcTemp = GetDC(_hwndPrev); if (hdcTemp) { HBITMAP hbmMem = CreateCompatibleBitmap(hdcTemp, RECTWIDTH(_rcOuter), RECTHEIGHT(_rcOuter)); if (hbmMem) { HBITMAP hbmOld = (HBITMAP) SelectObject(_hdcMem, hbmMem); DeleteObject(hbmOld); } else hr = E_FAIL; ReleaseDC(_hwndPrev, hdcTemp); } else hr = E_FAIL;
if (dwFlags & TMPREV_SHOWBKGND) { _fShowBack = TRUE; }
_fShowVS = dwFlags & TMPREV_SHOWVS; _fOnlyActiveWindow = _fShowIcons = dwFlags & TMPREV_SHOWICONS;
DEBUG_CODE(TraceMsg(TF_THEMEUI_PERF, "CPreviewTheme::CreatePreview() returned %#08lx. Time=%lums", hr, DebugStopWatch()));
if (SUCCEEDED(hr)) hr = UpdatePreview(pPropertyBag); }
return hr; }
//===========================
// *** IUnknown Interface ***
//===========================
ULONG CPreviewTheme::AddRef() { return InterlockedIncrement(&m_cRef); }
ULONG CPreviewTheme::Release() { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; }
HRESULT CPreviewTheme::QueryInterface(REFIID riid, void **ppvObj) { static const QITAB qit[] = { QITABENT(CPreviewTheme, IObjectWithSite), QITABENT(CPreviewTheme, IThemePreview), { 0 }, };
return QISearch(this, qit, riid, ppvObj); }
//===========================
// *** Class Methods ***
//===========================
CPreviewTheme::CPreviewTheme() : m_cRef(1) { DllAddRef();
// This needs to be allocated in Zero Inited Memory.
// Assert that all Member Variables are inited to Zero.
ASSERT(!m_pTheme); ASSERT(!m_pScheme); ASSERT(!m_pStyle); ASSERT(!m_pSize); ASSERT(!_hwndPrev); }
HRESULT CPreviewTheme::_Init(void) { HRESULT hr = S_OK;
_RegisterThemePreviewClass(HINST_THISDLL);
HDC hdc = GetDC(NULL); if (hdc) { _hdcMem = CreateCompatibleDC(hdc); ReleaseDC(NULL, hdc); } else hr = E_FAIL;
if (_hdcMem) { _hbmMon = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(IDB_MONITOR)); if (_hbmMon) { if (LoadString(HINST_THISDLL, IDS_NONE, _szNone, ARRAYSIZE(_szNone)) == 0) hr = E_FAIL; } else hr = E_FAIL;
if (SUCCEEDED(hr)) hr = CoCreateInstance(CLSID_Thumbnail, NULL, CLSCTX_INPROC_SERVER, IID_IThumbnail, (void **)&_pThumb); } else hr = E_FAIL;
if (FAILED(hr)) { if (_hbmMon) { DeleteObject(_hbmMon); _hbmMon = NULL; } if (_hdcMem) { DeleteDC(_hdcMem); _hdcMem = NULL; } }
return hr; }
CPreviewTheme::~CPreviewTheme() { if (_hwndPrev && IsWindow(_hwndPrev)) { DestroyWindow(_hwndPrev); _hwndPrev = NULL; } if (_hbmMon) { DeleteObject(_hbmMon); _hbmMon = NULL; } if (_hbmBack) { DeleteObject(_hbmBack); _hbmBack = NULL; } if (_hbrBack) { DeleteObject(_hbrBack); _hbrBack = NULL; }
if (_hbmVS) { DeleteObject(_hbmVS); }
if (_hdcMem) { DeleteDC(_hdcMem); _hpalMem = NULL; _hdcMem = NULL; }
if (_pActiveDesk) { _pActiveDesk->Release(); }
for (int i = 0; i < MAX_PREVIEW_ICONS; i++) { if (_iconList[i].hicon) { DestroyIcon(_iconList[i].hicon); } }
ATOMICRELEASE(m_pTheme); ATOMICRELEASE(m_pScheme); ATOMICRELEASE(m_pStyle); ATOMICRELEASE(m_pSize); ATOMICRELEASE(_pThumb);
DllRelease(); }
LRESULT CALLBACK CPreviewTheme::ThemePreviewWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { CPreviewTheme * pThis = (CPreviewTheme *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (pThis) return pThis->_ThemePreviewWndProc(hWnd, wMsg, wParam, lParam);
return DefWindowProc(hWnd, wMsg, wParam, lParam); }
LRESULT CPreviewTheme::_ThemePreviewWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch(wMsg) { case WM_CREATE: break;
case WM_DESTROY: { MSG msg; while (PeekMessage(&msg, hWnd, WM_HTML_BITMAP, WM_ASYNC_BITMAP, PM_REMOVE)) { if ( msg.lParam ) { if (msg.message == WM_ASYNC_BITMAP) { // clean up this useless stuff
DeleteObject(((PASYNCWALLPARAM)(msg.lParam))->hbmp); LocalFree((PASYNCWALLPARAM)(msg.lParam)); } else // WM_HTML_BITMAP
DeleteObject((HBITMAP)msg.lParam); } } } break;
case WM_PALETTECHANGED: break;
case WM_QUERYNEWPALETTE: break;
case WM_HTML_BITMAP: { // may come through with NULL if the image extraction failed....
if (wParam == _dwWallpaperID && lParam) { _fHTMLBitmap = TRUE; _iTileMode = _iNewTileMode; _putBackgroundBitmap((HBITMAP)lParam); // Take ownership of bitmap
return 1; } // Bitmap for something no longer selected
return 0; }
case WM_ASYNC_BITMAP: if (lParam) { PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) lParam; ASSERT(pawp->hbmp); if (pawp->id == _dwWallpaperID) { _fHTMLBitmap = FALSE; _iTileMode = _iNewTileMode; _putBackgroundBitmap(pawp->hbmp); } else { // clean up this useless stuff
DeleteObject(pawp->hbmp); LocalFree(pawp); } } break;
case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); _Paint(ps.hdc); EndPaint(hWnd, &ps); } return 0;
case WM_ERASEBKGND: _Paint((HDC)wParam); return 1;
}
return DefWindowProc(hWnd,wMsg,wParam,lParam); }
BOOL CPreviewTheme::_RegisterThemePreviewClass(HINSTANCE hInst) { WNDCLASS wc;
if (!GetClassInfo(hInst, THEMEPREV_CLASS, &wc)) { wc.style = 0; wc.lpfnWndProc = CPreviewTheme::ThemePreviewWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1); wc.lpszMenuName = NULL; wc.lpszClassName = THEMEPREV_CLASS;
if (!RegisterClass(&wc)) return FALSE; }
return TRUE; }
HRESULT CPreviewTheme::_putIcons(IPropertyBag* pPropertyBag) { HRESULT hr;
for (int i = 0; i < MAX_PREVIEW_ICONS; i++) { if (_iconList[i].hicon) { DestroyIcon(_iconList[i].hicon); }
WCHAR szIcon[MAX_PATH];
hr = SHPropertyBag_ReadStr(pPropertyBag, s_Icons[i], szIcon, ARRAYSIZE(szIcon)); if (SUCCEEDED(hr)) { WCHAR szIconModule[MAX_PATH]; SHExpandEnvironmentStrings(szIcon, szIconModule, ARRAYSIZE(szIconModule)); int iIndex = PathParseIconLocation(szIconModule); ExtractIconEx(szIconModule, iIndex, &_iconList[i].hicon, NULL, 1); } }
_fMemIsDirty = TRUE; InvalidateRect(_hwndPrev, &_rcInner, FALSE); return S_OK; }
HRESULT CPreviewTheme::_putVisualStyle(LPCWSTR pszVSPath, LPCWSTR pszVSColor, LPCWSTR pszVSSize, SYSTEMMETRICSALL* psysMet) { HRESULT hr = E_FAIL; HBITMAP hbmVS = NULL; HBITMAP hbmOldVS = NULL; HDC hdcVS = NULL;
if (!pszVSPath || !*pszVSPath) { HDC hdcTemp = GetDC(_hwndPrev);
if (hdcTemp) { hdcVS = CreateCompatibleDC(hdcTemp); hbmVS = CreateCompatibleBitmap(hdcTemp, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner)); hbmOldVS = (HBITMAP)SelectObject(hdcVS, hbmVS);
if (hdcVS && hbmVS) { RECT rcVS; rcVS.left = 0; rcVS.right = RECTWIDTH(_rcInner) - (_fShowIcons ? 100 : 8); rcVS.top = 0; rcVS.bottom = RECTHEIGHT(_rcInner) - (_fShowIcons ? 50 : 8);
// Create everyone including globals
HDC hdcVStemp = CreateCompatibleDC(hdcTemp); HBITMAP hbmVStemp = CreateCompatibleBitmap(hdcTemp, RECTWIDTH(rcVS), RECTHEIGHT(rcVS)); HBITMAP hbmOldVStemp = (HBITMAP) SelectObject(hdcVStemp, hbmVStemp);
if (hdcVStemp && hbmVStemp) { if (_fRTL) { SetLayout(hdcVStemp, LAYOUT_RTL); SetLayout(hdcVS, LAYOUT_RTL); }
HBRUSH hbr = CreateSolidBrush(RGB(255, 255, 0)); if (hbr) { FillRect(hdcVStemp, &rcVS, hbr); RECT rcTemp = {0, 0, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner)}; FillRect(hdcVS, &rcTemp, hbr); DeleteObject(hbr); }
// Render image at full size
hr = DrawAppearance(hdcVStemp, &rcVS, psysMet, _fOnlyActiveWindow, _fRTL);
// Shrink image to fit on "monitor"
int iX = _rcInner.left + (_fShowIcons ? 10 : RECTWIDTH(_rcInner) - RECTWIDTH(rcVS)); BitBlt(hdcVS, iX, _rcInner.top, RECTWIDTH(rcVS), RECTHEIGHT(rcVS), hdcVStemp, rcVS.left, rcVS.top, SRCCOPY); }
// Free temporary variables and store off globals
if (hdcVStemp) { SelectObject(hdcVStemp, hbmOldVStemp); DeleteDC(hdcVStemp); } if (hbmVStemp) { DeleteObject(hbmVStemp); } }
ReleaseDC(_hwndPrev, hdcTemp); } else hr = E_OUTOFMEMORY; } else { hr = S_OK; }
if (SUCCEEDED(hr)) { if (_hbmVS) { DeleteObject(_hbmVS); } _hbmVS = hbmVS; hbmVS = NULL;
_fMemIsDirty = TRUE; InvalidateRect(_hwndPrev, &_rcInner, FALSE); }
if (hdcVS) { if (hbmOldVS) { SelectObject(hdcVS, hbmOldVS); } DeleteDC(hdcVS); } if (hbmVS) { DeleteObject(hbmVS); }
return hr; }
HRESULT CPreviewTheme::_putBackgroundBitmap(HBITMAP hbm) { if (_hbmBack) { DeleteObject(_hbmBack); _hbmBack = NULL; }
if (_hpalMem) { DeleteObject(_hpalMem); _hpalMem = NULL; }
_hbmBack = hbm;
if (_hbmBack) { BITMAP bm; GetObject(_hbmBack, sizeof(bm), &bm);
if (GetDeviceCaps(_hdcMem, RASTERCAPS) & RC_PALETTE) { if (bm.bmBitsPixel * bm.bmPlanes > 8) _hpalMem = CreateHalftonePalette(_hdcMem); else if (bm.bmBitsPixel * bm.bmPlanes == 8) _PaletteFromDS(_hdcMem, &_hpalMem); else _hpalMem = NULL; //!!! assume 1 or 4bpp images dont have palettes
} }
_fMemIsDirty = TRUE; InvalidateRect(_hwndPrev, &_rcInner, FALSE);
return S_OK; }
HRESULT CPreviewTheme::_putBackground(BSTR bstrBackground, BOOL fPattern, int iTileMode) { if (fPattern) { TCHAR szBuf[MAX_PATH];
// get rid of old brush if there was one
if (_hbrBack) DeleteObject(_hbrBack);
if (bstrBackground && lstrcmpi(bstrBackground, _szNone)) { WORD patbits[CXYDESKPATTERN] = {0, 0, 0, 0, 0, 0, 0, 0};
if (GetPrivateProfileString(TEXT("patterns"), bstrBackground, TEXT(""), szBuf, ARRAYSIZE(szBuf), TEXT("control.ini"))) { _ReadPattern(szBuf, patbits); }
HBITMAP hbmTemp = CreateBitmap(8, 8, 1, 1, patbits); if (hbmTemp) { _hbrBack = CreatePatternBrush(hbmTemp); DeleteObject(hbmTemp); } } else { _hbrBack = CreateSolidBrush(_systemMetricsAll.schemeData.rgb[COLOR_BACKGROUND]); } if (!_hbrBack) _hbrBack = (HBRUSH) GetStockObject(BLACK_BRUSH);
_fMemIsDirty = TRUE; InvalidateRect(_hwndPrev, &_rcInner, FALSE); } else { _iNewTileMode = iTileMode; return _GetWallpaperAsync(bstrBackground); } return S_OK; }
/*-------------------------------------------------------------
** given a pattern string from an ini file, return the pattern ** in a binary (ie useful) form. **-------------------------------------------------------------*/ HRESULT CPreviewTheme::_ReadPattern(LPTSTR lpStr, WORD FAR *patbits) { short i, val;
/* Get eight groups of numbers seprated by non-numeric characters. */ for (i = 0; i < CXYDESKPATTERN; i++) { val = 0; if (*lpStr != TEXT('\0')) { /* Skip over any non-numeric characters. */ while (!(*lpStr >= TEXT('0') && *lpStr <= TEXT('9'))) lpStr++;
/* Get the next series of digits. */ while (*lpStr >= TEXT('0') && *lpStr <= TEXT('9')) val = val*10 + *lpStr++ - TEXT('0'); }
patbits[i] = val; }
return S_OK; }
/*----------------------------------------------------------------------------*\
\*----------------------------------------------------------------------------*/ HRESULT CPreviewTheme::_PaletteFromDS(HDC hdc, HPALETTE* phPalette) { DWORD adw[257]; int i,n;
n = GetDIBColorTable(hdc, 0, 256, (LPRGBQUAD)&adw[1]); adw[0] = MAKELONG(0x300, n);
for (i=1; i<=n; i++) adw[i] = RGB(GetBValue(adw[i]),GetGValue(adw[i]),GetRValue(adw[i]));
*phPalette = (n == 0) ? NULL : CreatePalette((LPLOGPALETTE)&adw[0]);
return S_OK; }
HRESULT CPreviewTheme::_DrawMonitor(HDC hdc) { HBITMAP hbmT; HDC hdcMon; BITMAP bmMon;
if (_hbmMon == NULL) { return E_OUTOFMEMORY; }
//
// convert the "base" of the monitor to the right color.
//
// the lower left of the bitmap has a transparent color
// we fixup using FloodFill
//
hdcMon = CreateCompatibleDC(NULL); if (hdcMon) { hbmT = (HBITMAP) SelectObject(hdcMon, _hbmMon);
GetObject(_hbmMon, sizeof(bmMon), &bmMon);
FillRect(hdc, &_rcOuter, GetSysColorBrush(COLOR_3DFACE)); DrawThemeParentBackground(_hwndPrev, hdc, NULL); TransparentBlt(hdc, _rcOuter.left + _cxMon, _rcOuter.top + _cyMon, bmMon.bmWidth, bmMon.bmHeight, hdcMon, 0, 0, bmMon.bmWidth, bmMon.bmHeight, RGB(255, 0, 255));
// clean up after ourselves
SelectObject(hdcMon, hbmT); DeleteDC(hdcMon); }
return S_OK; }
HRESULT CPreviewTheme::_DrawBackground(HDC hdc) { // Draw Pattern first
if (_hbrBack) { COLORREF clrOldText = SetTextColor(hdc, GetSysColor(COLOR_BACKGROUND)); COLORREF clrOldBk = SetBkColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); HBRUSH hbr = (HBRUSH) SelectObject(hdc, _hbrBack);
PatBlt(hdc, _rcInner.left, _rcInner.top, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner), PATCOPY);
SelectObject(hdc, hbr); SetTextColor(hdc, clrOldText); SetBkColor(hdc, clrOldBk); }
/// Start Draw Wall Paper
if (_hbmBack && _fShowBack) { HDC hdcBack = CreateCompatibleDC(hdc); if (hdcBack) { HBITMAP hbmOldBack = (HBITMAP)SelectObject(hdcBack, _hbmBack); BITMAP bm;
GetObject(_hbmBack, sizeof(bm), &bm);
int dxBack = MulDiv(bm.bmWidth, RECTWIDTH(_rcInner), GetDeviceCaps(hdc, HORZRES)); int dyBack = MulDiv(bm.bmHeight, RECTHEIGHT(_rcInner), GetDeviceCaps(hdc, VERTRES));
if (dxBack < 1) dxBack = 1; if (dyBack < 1) dyBack = 1;
if (_hpalMem) { SelectPalette(hdc, _hpalMem, TRUE); RealizePalette(hdc); }
IntersectClipRect(hdc, _rcInner.left, _rcInner.top, _rcInner.right, _rcInner.bottom); SetStretchBltMode(hdc, COLORONCOLOR);
if ((_iTileMode == WPSTYLE_TILE) && (!_fHTMLBitmap)) { int i; StretchBlt(hdc, _rcInner.left, _rcInner.top, dxBack, dyBack, hdcBack, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
for (i = _rcInner.left+dxBack; i < (_rcInner.left + RECTWIDTH(_rcInner)); i+= dxBack) BitBlt(hdc, i, _rcInner.top, dxBack, dyBack, hdc, _rcInner.left, _rcInner.top, SRCCOPY);
for (i = _rcInner.top; i < (_rcInner.top + RECTHEIGHT(_rcInner)); i += dyBack) BitBlt(hdc, _rcInner.left, i, RECTWIDTH(_rcInner), dyBack, hdc, _rcInner.left, _rcInner.top, SRCCOPY); } else { //We want to stretch the Bitmap to the preview monitor size ONLY for new platforms.
if ((_iTileMode == WPSTYLE_STRETCH) || (_fHTMLBitmap)) { //Stretch the bitmap to the whole preview monitor.
dxBack = RECTWIDTH(_rcInner); dyBack = RECTHEIGHT(_rcInner); } //Center the bitmap in the preview monitor
StretchBlt(hdc, _rcInner.left + (RECTWIDTH(_rcInner) - dxBack)/2, _rcInner.top + (RECTHEIGHT(_rcInner) - dyBack)/2, dxBack, dyBack, hdcBack, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); }
// restore dc
SelectPalette(hdc, (HPALETTE) GetStockObject(DEFAULT_PALETTE), TRUE); SelectClipRgn(hdc, NULL);
SelectObject(hdcBack, hbmOldBack); DeleteDC(hdcBack); } }
return S_OK; }
HRESULT CPreviewTheme::_DrawVisualStyle(HDC hdc) { if (_hbmVS) { HDC hdcVS = CreateCompatibleDC(hdc); if (hdcVS) { HBITMAP hbmOldVS = (HBITMAP)SelectObject(hdcVS, _hbmVS);
TransparentBlt(hdc, _rcInner.left, _rcInner.top, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner), hdcVS, 0, 0, RECTWIDTH(_rcInner), RECTHEIGHT(_rcInner), RGB(255, 255, 0));
SelectObject(hdcVS, hbmOldVS); DeleteDC(hdcVS); } } else { RECT rc; rc.left = _fShowIcons ? 20 : 8; rc.right = RECTWIDTH(_rcInner) - (_fShowIcons ? 100 : 8); rc.top = _fShowIcons ? 10 : 8; rc.bottom = RECTHEIGHT(_rcInner) - (_fShowIcons ? 60 : 20); DrawNCPreview(hdc, NCPREV_ACTIVEWINDOW | (_fOnlyActiveWindow ? 0 : NCPREV_MESSAGEBOX | NCPREV_INACTIVEWINDOW) | (_fRTL ? NCPREV_RTL : 0) , &rc, _szVSPath, _szVSColor, _szVSSize, &(_systemMetricsAll.schemeData.ncm), (_systemMetricsAll.schemeData.rgb)); }
return S_OK; }
HRESULT CPreviewTheme::_DrawIcons(HDC hdc) { int y = RECTHEIGHT(_rcInner) - _systemMetricsAll.nIcon - 8; int x = RECTWIDTH(_rcInner) - _systemMetricsAll.nIcon - 20;
DrawIcon(hdc, x, y, _iconList[3].hicon);
return S_OK; }
HRESULT CPreviewTheme::_Paint(HDC hdc) { HPALETTE hpalOld = NULL;
if (_fMemIsDirty) { if (_fRTL) { SetLayout(_hdcMem, LAYOUT_RTL); }
// Rebuild Back Buffer
if (_fShowMon) _DrawMonitor(_hdcMem);
// Always draw the background, the Background switch turns the background
// image on/off
_DrawBackground(_hdcMem);
if (_fShowIcons) _DrawIcons(_hdcMem);
if (_fShowVS) _DrawVisualStyle(_hdcMem);
_fMemIsDirty = FALSE; }
if (_hdcMem) { if (_hpalMem) { hpalOld = SelectPalette(hdc, _hpalMem, FALSE); RealizePalette(hdc); }
if (_fRTL) { SetLayout(hdc, LAYOUT_RTL); }
BitBlt(hdc, _rcOuter.left, _rcOuter.top, RECTWIDTH(_rcOuter), RECTHEIGHT(_rcOuter), _hdcMem, 0, 0, SRCCOPY);
if (_hpalMem) { SelectPalette(hdc, hpalOld, TRUE); RealizePalette(hdc); } }
return S_OK; }
DWORD CALLBACK UpdateWallProc(LPVOID pv) { ASSERT(pv); if (pv) { PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) pv; pawp->hbmp = (HBITMAP)LoadImage(NULL, pawp->szFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
if (pawp->hbmp) { // if all is good, then the window will handle cleaning up
if (IsWindow(pawp->hwnd) && PostMessage(pawp->hwnd, WM_ASYNC_BITMAP, 0, (LPARAM)pawp)) return TRUE;
DeleteObject(pawp->hbmp); }
LocalFree(pawp); }
return TRUE; }
const GUID CLSID_HtmlThumbnailExtractor = {0xeab841a0, 0x9550, 0x11cf, 0x8c, 0x16, 0x0, 0x80, 0x5f, 0x14, 0x8, 0xf3};
DWORD CALLBACK UpdateWallProcHTML(LPVOID pv) { if (SUCCEEDED(CoInitialize(NULL))) { ASSERT(pv); if (pv) { PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) pv; IPersistFile *ppf; HRESULT hr = CoCreateInstance(CLSID_HtmlThumbnailExtractor, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPersistFile, &ppf)); if (SUCCEEDED(hr)) { hr = ppf->Load(pawp->szFile, STGM_READ); if (SUCCEEDED(hr)) { IExtractImage *pei= NULL; hr = ppf->QueryInterface(IID_PPV_ARG(IExtractImage, &pei)); if (SUCCEEDED(hr)) { DWORD dwPriority = 0; DWORD dwFlags = IEIFLAG_SCREEN | IEIFLAG_OFFLINE; WCHAR szLocation[MAX_PATH]; HDC hdc = GetDC(NULL); SIZEL rgSize = {GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES)}; ReleaseDC(NULL, hdc); hr = pei->GetLocation(szLocation, ARRAYSIZE(szLocation), &dwPriority, &rgSize, SHGetCurColorRes(), &dwFlags); if (SUCCEEDED(hr)) { HBITMAP hbm; hr = pei->Extract(&hbm); if (SUCCEEDED(hr)) { if (!SendMessage(pawp->hwnd, WM_HTML_BITMAP, pawp->id, (LPARAM)hbm)) { DeleteObject(hbm); } } } pei->Release(); } } ppf->Release(); } LocalFree(pawp); } CoUninitialize(); }
return TRUE; }
//
// Determines if the wallpaper can be supported in non-active desktop mode.
//
BOOL CPreviewTheme::_IsNormalWallpaper(LPCWSTR pszFileName) { BOOL fRet = TRUE;
if (pszFileName[0] == TEXT('\0')) { fRet = TRUE; } else { LPTSTR pszExt = PathFindExtension(pszFileName);
//Check for specific files that can be shown only in ActiveDesktop mode!
if((lstrcmpi(pszExt, TEXT(".GIF")) == 0) || (lstrcmpi(pszExt, TEXT(".gif")) == 0) || // 368690: Strange, but we must compare 'i' in both caps and lower case.
(lstrcmpi(pszExt, TEXT(".JPG")) == 0) || (lstrcmpi(pszExt, TEXT(".JPE")) == 0) || (lstrcmpi(pszExt, TEXT(".JPEG")) == 0) || (lstrcmpi(pszExt, TEXT(".PNG")) == 0) || (lstrcmpi(pszExt, TEXT(".HTM")) == 0) || (lstrcmpi(pszExt, TEXT(".HTML")) == 0) || (lstrcmpi(pszExt, TEXT(".HTT")) == 0)) return FALSE;
//Everything else (including *.BMP files) are "normal" wallpapers
} return fRet; }
//
// Determines if the wallpaper is a picture (vs. HTML).
//
BOOL CPreviewTheme::_IsWallpaperPicture(LPCWSTR pszWallpaper) { BOOL fRet = TRUE;
if (pszWallpaper[0] == TEXT('\0')) { //
// Empty wallpapers count as empty pictures.
//
fRet = TRUE; } else { LPTSTR pszExt = PathFindExtension(pszWallpaper);
if ((lstrcmpi(pszExt, TEXT(".HTM")) == 0) || (lstrcmpi(pszExt, TEXT(".HTML")) == 0) || (lstrcmpi(pszExt, TEXT(".HTT")) == 0)) { fRet = FALSE; } }
return fRet; }
HRESULT CPreviewTheme::_LoadWallpaperAsync(LPCWSTR pszFile, DWORD dwID, BOOL bHTML) { PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) LocalAlloc(LPTR, SIZEOF(ASYNCWALLPARAM)); HRESULT hr = E_OUTOFMEMORY;
if (pawp) { pawp->hwnd = _hwndPrev; pawp->id = dwID; hr = StringCchCopy(pawp->szFile, ARRAYSIZE(pawp->szFile), pszFile); if (SUCCEEDED(hr)) { if (bHTML) { if (!SHQueueUserWorkItem(UpdateWallProcHTML, pawp, 0, (DWORD_PTR)0, (DWORD_PTR *)NULL, NULL, 0)) { LocalFree(pawp); } } else { if (!SHQueueUserWorkItem(UpdateWallProc, pawp, 0, (DWORD_PTR)0, (DWORD_PTR *)NULL, NULL, 0)) { LocalFree(pawp); } } } }
return S_OK; }
HRESULT CPreviewTheme::_GetWallpaperAsync(LPWSTR psz) { HRESULT hr = S_OK; WCHAR wszWallpaper[INTERNET_MAX_URL_LENGTH]; LPWSTR pszWallpaper = psz; _dwWallpaperID++;
if (*pszWallpaper && lstrcmpi(pszWallpaper, _szNone)) { if (_IsNormalWallpaper(pszWallpaper)) { _LoadWallpaperAsync(pszWallpaper, _dwWallpaperID, FALSE); } else { if(_IsWallpaperPicture(pszWallpaper)) { pszWallpaper = wszWallpaper; // This is a picture (GIF, JPG etc.,)
// We need to generate a small HTML file that has this picture
// as the background image.
//
// Compute the filename for the Temporary HTML file.
//
GetTempPath(ARRAYSIZE(wszWallpaper), wszWallpaper); StringCchCat(wszWallpaper, ARRAYSIZE(wszWallpaper), PREVIEW_PICTURE_FILENAME); //
// Generate the preview picture html file.
//
if (!_pActiveDesk) { hr = _GetActiveDesktop(&_pActiveDesk); }
if (SUCCEEDED(hr)) { _pActiveDesk->SetWallpaper(psz, 0);
WALLPAPEROPT wpo = { sizeof(WALLPAPEROPT) }; wpo.dwStyle = _iNewTileMode; _pActiveDesk->SetWallpaperOptions(&wpo, 0);
_pActiveDesk->GenerateDesktopItemHtml(wszWallpaper, NULL, 0); } }
_LoadWallpaperAsync(pszWallpaper, _dwWallpaperID, TRUE); } } else { _putBackgroundBitmap(NULL); }
return hr; }
HRESULT CPreviewTheme::_GetActiveDesktop(IActiveDesktop ** ppActiveDesktop) { HRESULT hr = S_OK;
if (!*ppActiveDesktop) { IActiveDesktopP * piadp;
if (SUCCEEDED(hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktopP, &piadp)) )) { WCHAR wszScheme[MAX_PATH]; DWORD dwcch = ARRAYSIZE(wszScheme);
// Get the global "edit" scheme and set ourselves us to read from and edit that scheme
if (SUCCEEDED(piadp->GetScheme(wszScheme, &dwcch, SCHEME_GLOBAL | SCHEME_EDIT))) { piadp->SetScheme(wszScheme, SCHEME_LOCAL); } hr = piadp->QueryInterface(IID_PPV_ARG(IActiveDesktop, ppActiveDesktop)); piadp->Release(); } } else { (*ppActiveDesktop)->AddRef(); }
return hr; }
HRESULT CThemePreview_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj) { HRESULT hr = E_INVALIDARG;
if (punkOuter) { return CLASS_E_NOAGGREGATION; }
if (ppvObj) { CPreviewTheme * pObject = new CPreviewTheme();
*ppvObj = NULL; if (pObject) { hr = pObject->_Init(); if (SUCCEEDED(hr)) { hr = pObject->QueryInterface(riid, ppvObj); } pObject->Release(); } else { hr = E_OUTOFMEMORY; } }
return hr; }
|