diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/thmutil.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/thmutil.cpp | 650 |
1 files changed, 275 insertions, 375 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp index e8c23b6c..9adc2ddd 100644 --- a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp | |||
@@ -44,7 +44,6 @@ const DWORD THEME_INVALID_ID = 0xFFFFFFFF; | |||
44 | const COLORREF THEME_INVISIBLE_COLORREF = 0xFFFFFFFF; | 44 | const COLORREF THEME_INVISIBLE_COLORREF = 0xFFFFFFFF; |
45 | const DWORD GROW_FONT_INSTANCES = 3; | 45 | const DWORD GROW_FONT_INSTANCES = 3; |
46 | const DWORD GROW_IMAGE_INSTANCES = 5; | 46 | const DWORD GROW_IMAGE_INSTANCES = 5; |
47 | const DWORD GROW_WINDOW_TEXT = 250; | ||
48 | 47 | ||
49 | static Gdiplus::GdiplusStartupInput vgsi; | 48 | static Gdiplus::GdiplusStartupInput vgsi; |
50 | static Gdiplus::GdiplusStartupOutput vgso = { }; | 49 | static Gdiplus::GdiplusStartupOutput vgso = { }; |
@@ -70,16 +69,29 @@ enum INTERNAL_CONTROL_STYLE | |||
70 | INTERNAL_CONTROL_STYLE_OWNER_DRAW = 0x0010, | 69 | INTERNAL_CONTROL_STYLE_OWNER_DRAW = 0x0010, |
71 | }; | 70 | }; |
72 | 71 | ||
73 | struct MEMBUFFER_FOR_RICHEDIT | ||
74 | { | ||
75 | BYTE* rgbData; | ||
76 | DWORD cbData; | ||
77 | 72 | ||
78 | DWORD iData; | 73 | // prototypes |
79 | }; | 74 | /******************************************************************** |
75 | ThemeHoverControl - mark a control as hover. | ||
76 | |||
77 | *******************************************************************/ | ||
78 | static BOOL ThemeHoverControl( | ||
79 | __in THEME* pTheme, | ||
80 | __in HWND hwndParent, | ||
81 | __in HWND hwndControl | ||
82 | ); | ||
80 | 83 | ||
84 | /******************************************************************** | ||
85 | ThemeSetControlColor - sets the color of text for a control. | ||
86 | |||
87 | *******************************************************************/ | ||
88 | static BOOL ThemeSetControlColor( | ||
89 | __in THEME* pTheme, | ||
90 | __in HDC hdc, | ||
91 | __in HWND hWnd, | ||
92 | __out HBRUSH* phBackgroundBrush | ||
93 | ); | ||
81 | 94 | ||
82 | // prototypes | ||
83 | static HRESULT RegisterWindowClasses( | 95 | static HRESULT RegisterWindowClasses( |
84 | __in_opt HMODULE hModule | 96 | __in_opt HMODULE hModule |
85 | ); | 97 | ); |
@@ -258,11 +270,11 @@ static HRESULT ParseNotes( | |||
258 | ); | 270 | ); |
259 | static HRESULT StopBillboard( | 271 | static HRESULT StopBillboard( |
260 | __in THEME* pTheme, | 272 | __in THEME* pTheme, |
261 | __in DWORD dwControl | 273 | __in THEME_CONTROL* pControl |
262 | ); | 274 | ); |
263 | static HRESULT StartBillboard( | 275 | static HRESULT StartBillboard( |
264 | __in THEME* pTheme, | 276 | __in THEME* pTheme, |
265 | __in DWORD dwControl | 277 | __in THEME_CONTROL* pControl |
266 | ); | 278 | ); |
267 | static HRESULT EnsureFontInstance( | 279 | static HRESULT EnsureFontInstance( |
268 | __in THEME* pTheme, | 280 | __in THEME* pTheme, |
@@ -290,7 +302,6 @@ static HRESULT LoadControls( | |||
290 | __in_opt THEME_CONTROL* pParentControl | 302 | __in_opt THEME_CONTROL* pParentControl |
291 | ); | 303 | ); |
292 | static HRESULT ShowControl( | 304 | static HRESULT ShowControl( |
293 | __in THEME* pTheme, | ||
294 | __in THEME_CONTROL* pControl, | 305 | __in THEME_CONTROL* pControl, |
295 | __in int nCmdShow, | 306 | __in int nCmdShow, |
296 | __in BOOL fSaveEditboxes, | 307 | __in BOOL fSaveEditboxes, |
@@ -376,18 +387,6 @@ static BOOL DrawHoverControl( | |||
376 | __in THEME* pTheme, | 387 | __in THEME* pTheme, |
377 | __in BOOL fHover | 388 | __in BOOL fHover |
378 | ); | 389 | ); |
379 | static DWORD CALLBACK RichEditStreamFromFileHandleCallback( | ||
380 | __in DWORD_PTR dwCookie, | ||
381 | __in_bcount(cb) LPBYTE pbBuff, | ||
382 | __in LONG cb, | ||
383 | __in LONG *pcb | ||
384 | ); | ||
385 | static DWORD CALLBACK RichEditStreamFromMemoryCallback( | ||
386 | __in DWORD_PTR dwCookie, | ||
387 | __in_bcount(cb) LPBYTE pbBuff, | ||
388 | __in LONG cb, | ||
389 | __in LONG *pcb | ||
390 | ); | ||
391 | static void FreeFontInstance( | 390 | static void FreeFontInstance( |
392 | __in THEME_FONT_INSTANCE* pFontInstance | 391 | __in THEME_FONT_INSTANCE* pFontInstance |
393 | ); | 392 | ); |
@@ -475,6 +474,11 @@ static BOOL OnWmNotify( | |||
475 | __in const THEME_CONTROL* pThemeControl, | 474 | __in const THEME_CONTROL* pThemeControl, |
476 | __inout LRESULT* plResult | 475 | __inout LRESULT* plResult |
477 | ); | 476 | ); |
477 | static const THEME_CONTROL* FindControlFromId( | ||
478 | __in const THEME* pTheme, | ||
479 | __in WORD wId, | ||
480 | __in_opt const THEME_CONTROL* pParentControl = NULL | ||
481 | ); | ||
478 | static const THEME_CONTROL* FindControlFromHWnd( | 482 | static const THEME_CONTROL* FindControlFromHWnd( |
479 | __in const THEME* pTheme, | 483 | __in const THEME* pTheme, |
480 | __in HWND hWnd, | 484 | __in HWND hWnd, |
@@ -974,83 +978,39 @@ LExit: | |||
974 | 978 | ||
975 | 979 | ||
976 | DAPI_(HRESULT) ThemeLoadRichEditFromFile( | 980 | DAPI_(HRESULT) ThemeLoadRichEditFromFile( |
977 | __in THEME* pTheme, | 981 | __in const THEME_CONTROL* pThemeControl, |
978 | __in DWORD dwControl, | ||
979 | __in_z LPCWSTR wzFileName, | 982 | __in_z LPCWSTR wzFileName, |
980 | __in HMODULE hModule | 983 | __in HMODULE hModule |
981 | ) | 984 | ) |
982 | { | 985 | { |
983 | HRESULT hr = S_OK; | 986 | HRESULT hr = E_INVALIDARG; |
984 | LPWSTR sczFile = NULL; | ||
985 | HANDLE hFile = INVALID_HANDLE_VALUE; | ||
986 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | ||
987 | |||
988 | hr = PathRelativeToModule(&sczFile, wzFileName, hModule); | ||
989 | ThmExitOnFailure(hr, "Failed to read resource data."); | ||
990 | 987 | ||
991 | hFile = ::CreateFileW(sczFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); | 988 | if (pThemeControl) |
992 | if (INVALID_HANDLE_VALUE == hFile) | ||
993 | { | 989 | { |
994 | ThmExitWithLastError(hr, "Failed to open RTF file."); | 990 | AssertSz(THEME_CONTROL_TYPE_RICHEDIT == pThemeControl->type, "ThemeLoadRichEditFromFile called for non-RichEdit control."); |
995 | } | ||
996 | else | ||
997 | { | ||
998 | LONGLONG llRtfSize; | ||
999 | hr = FileSizeByHandle(hFile, &llRtfSize); | ||
1000 | if (SUCCEEDED(hr)) | ||
1001 | { | ||
1002 | ::SendMessageW(hWnd, EM_EXLIMITTEXT, 0, static_cast<LPARAM>(llRtfSize)); | ||
1003 | } | ||
1004 | |||
1005 | EDITSTREAM es = { }; | ||
1006 | es.pfnCallback = RichEditStreamFromFileHandleCallback; | ||
1007 | es.dwCookie = reinterpret_cast<DWORD_PTR>(hFile); | ||
1008 | 991 | ||
1009 | ::SendMessageW(hWnd, EM_STREAMIN, SF_RTF, reinterpret_cast<LPARAM>(&es)); | 992 | hr = WnduLoadRichEditFromFile(pThemeControl->hWnd, wzFileName, hModule); |
1010 | hr = es.dwError; | ||
1011 | ThmExitOnFailure(hr, "Failed to update RTF stream."); | ||
1012 | } | 993 | } |
1013 | 994 | ||
1014 | LExit: | ||
1015 | ReleaseStr(sczFile); | ||
1016 | ReleaseFile(hFile); | ||
1017 | |||
1018 | return hr; | 995 | return hr; |
1019 | } | 996 | } |
1020 | 997 | ||
1021 | 998 | ||
1022 | DAPI_(HRESULT) ThemeLoadRichEditFromResource( | 999 | DAPI_(HRESULT) ThemeLoadRichEditFromResource( |
1023 | __in THEME* pTheme, | 1000 | __in const THEME_CONTROL* pThemeControl, |
1024 | __in DWORD dwControl, | ||
1025 | __in_z LPCSTR szResourceName, | ||
1026 | __in HMODULE hModule | ||
1027 | ) | ||
1028 | { | ||
1029 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | ||
1030 | return ThemeLoadRichEditFromResourceToHWnd(hWnd, szResourceName, hModule); | ||
1031 | } | ||
1032 | |||
1033 | DAPI_(HRESULT) ThemeLoadRichEditFromResourceToHWnd( | ||
1034 | __in HWND hWnd, | ||
1035 | __in_z LPCSTR szResourceName, | 1001 | __in_z LPCSTR szResourceName, |
1036 | __in HMODULE hModule | 1002 | __in HMODULE hModule |
1037 | ) | 1003 | ) |
1038 | { | 1004 | { |
1039 | HRESULT hr = S_OK; | 1005 | HRESULT hr = E_INVALIDARG; |
1040 | MEMBUFFER_FOR_RICHEDIT buffer = { }; | ||
1041 | EDITSTREAM es = { }; | ||
1042 | |||
1043 | hr = ResReadData(hModule, szResourceName, reinterpret_cast<LPVOID*>(&buffer.rgbData), &buffer.cbData); | ||
1044 | ThmExitOnFailure(hr, "Failed to read resource data."); | ||
1045 | 1006 | ||
1046 | es.pfnCallback = RichEditStreamFromMemoryCallback; | 1007 | if (pThemeControl) |
1047 | es.dwCookie = reinterpret_cast<DWORD_PTR>(&buffer); | 1008 | { |
1009 | AssertSz(THEME_CONTROL_TYPE_RICHEDIT == pThemeControl->type, "ThemeLoadRichEditFromResource called for non-RichEdit control."); | ||
1048 | 1010 | ||
1049 | ::SendMessageW(hWnd, EM_STREAMIN, SF_RTF, reinterpret_cast<LPARAM>(&es)); | 1011 | hr = WnduLoadRichEditFromResource(pThemeControl->hWnd, szResourceName, hModule); |
1050 | hr = es.dwError; | 1012 | } |
1051 | ThmExitOnFailure(hr, "Failed to update RTF stream."); | ||
1052 | 1013 | ||
1053 | LExit: | ||
1054 | return hr; | 1014 | return hr; |
1055 | } | 1015 | } |
1056 | 1016 | ||
@@ -1293,141 +1253,127 @@ LExit: | |||
1293 | } | 1253 | } |
1294 | 1254 | ||
1295 | 1255 | ||
1296 | DAPI_(BOOL) ThemeControlExists( | 1256 | DAPI_(BOOL) ThemeControlExistsByHWnd( |
1297 | __in const THEME* pTheme, | 1257 | __in const THEME* pTheme, |
1298 | __in DWORD dwControl | 1258 | __in HWND hWnd, |
1259 | __out_opt const THEME_CONTROL** ppThemeControl | ||
1299 | ) | 1260 | ) |
1300 | { | 1261 | { |
1301 | BOOL fExists = FALSE; | 1262 | const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd); |
1302 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1263 | |
1303 | if (hWnd) | 1264 | if (ppThemeControl) |
1304 | { | 1265 | { |
1305 | const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd); | 1266 | *ppThemeControl = pControl; |
1306 | fExists = (pControl && hWnd == pControl->hWnd); | ||
1307 | } | 1267 | } |
1308 | 1268 | ||
1309 | return fExists; | 1269 | return NULL != pControl; |
1270 | } | ||
1271 | |||
1272 | |||
1273 | DAPI_(BOOL) ThemeControlExistsById( | ||
1274 | __in const THEME* pTheme, | ||
1275 | __in WORD wId, | ||
1276 | __out_opt const THEME_CONTROL** ppThemeControl | ||
1277 | ) | ||
1278 | { | ||
1279 | const THEME_CONTROL* pControl = FindControlFromId(pTheme, wId); | ||
1280 | |||
1281 | if (ppThemeControl) | ||
1282 | { | ||
1283 | *ppThemeControl = pControl; | ||
1284 | } | ||
1285 | |||
1286 | return NULL != pControl; | ||
1310 | } | 1287 | } |
1311 | 1288 | ||
1312 | 1289 | ||
1313 | DAPI_(void) ThemeControlEnable( | 1290 | DAPI_(void) ThemeControlEnable( |
1314 | __in THEME* pTheme, | 1291 | __in const THEME_CONTROL* pThemeControl, |
1315 | __in DWORD dwControl, | ||
1316 | __in BOOL fEnable | 1292 | __in BOOL fEnable |
1317 | ) | 1293 | ) |
1318 | { | 1294 | { |
1319 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1295 | if (pThemeControl) |
1320 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd)); | ||
1321 | if (pControl) | ||
1322 | { | 1296 | { |
1297 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl); | ||
1323 | pControl->dwInternalStyle = fEnable ? (pControl->dwInternalStyle & ~INTERNAL_CONTROL_STYLE_DISABLED) : (pControl->dwInternalStyle | INTERNAL_CONTROL_STYLE_DISABLED); | 1298 | pControl->dwInternalStyle = fEnable ? (pControl->dwInternalStyle & ~INTERNAL_CONTROL_STYLE_DISABLED) : (pControl->dwInternalStyle | INTERNAL_CONTROL_STYLE_DISABLED); |
1324 | ::EnableWindow(hWnd, fEnable); | 1299 | ::EnableWindow(pControl->hWnd, fEnable); |
1325 | 1300 | ||
1326 | if (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_HIDE_WHEN_DISABLED) | 1301 | if (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_HIDE_WHEN_DISABLED) |
1327 | { | 1302 | { |
1328 | ::ShowWindow(hWnd, fEnable ? SW_SHOW : SW_HIDE); | 1303 | ::ShowWindow(pControl->hWnd, fEnable ? SW_SHOW : SW_HIDE); |
1329 | } | 1304 | } |
1330 | } | 1305 | } |
1331 | } | 1306 | } |
1332 | 1307 | ||
1333 | 1308 | ||
1334 | DAPI_(BOOL) ThemeControlEnabled( | 1309 | DAPI_(BOOL) ThemeControlEnabled( |
1335 | __in THEME* pTheme, | 1310 | __in const THEME_CONTROL* pThemeControl |
1336 | __in DWORD dwControl | ||
1337 | ) | 1311 | ) |
1338 | { | 1312 | { |
1339 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1313 | BOOL fEnabled = FALSE; |
1340 | const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd); | 1314 | |
1341 | return pControl && !(pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_DISABLED); | 1315 | if (pThemeControl) |
1316 | { | ||
1317 | fEnabled = !(pThemeControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_DISABLED); | ||
1318 | } | ||
1319 | |||
1320 | return fEnabled; | ||
1342 | } | 1321 | } |
1343 | 1322 | ||
1344 | 1323 | ||
1345 | DAPI_(void) ThemeControlElevates( | 1324 | DAPI_(void) ThemeControlElevates( |
1346 | __in THEME* pTheme, | 1325 | __in const THEME_CONTROL* pThemeControl, |
1347 | __in DWORD dwControl, | ||
1348 | __in BOOL fElevates | 1326 | __in BOOL fElevates |
1349 | ) | 1327 | ) |
1350 | { | 1328 | { |
1351 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1329 | if (pThemeControl) |
1352 | ::SendMessageW(hWnd, BCM_SETSHIELD, 0, fElevates); | 1330 | { |
1331 | ::SendMessageW(pThemeControl->hWnd, BCM_SETSHIELD, 0, fElevates); | ||
1332 | } | ||
1353 | } | 1333 | } |
1354 | 1334 | ||
1355 | 1335 | ||
1356 | DAPI_(void) ThemeShowControl( | 1336 | DAPI_(void) ThemeShowControl( |
1357 | __in THEME* pTheme, | 1337 | __in const THEME_CONTROL* pThemeControl, |
1358 | __in DWORD dwControl, | ||
1359 | __in int nCmdShow | 1338 | __in int nCmdShow |
1360 | ) | 1339 | ) |
1361 | { | 1340 | { |
1362 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1341 | if (pThemeControl) |
1363 | ::ShowWindow(hWnd, nCmdShow); | ||
1364 | |||
1365 | // Save the control's visible state. | ||
1366 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd)); | ||
1367 | if (pControl) | ||
1368 | { | 1342 | { |
1343 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl); | ||
1344 | ::ShowWindow(pControl->hWnd, nCmdShow); | ||
1345 | |||
1346 | // Save the control's visible state. | ||
1369 | pControl->dwInternalStyle = (SW_HIDE == nCmdShow) ? (pControl->dwInternalStyle | INTERNAL_CONTROL_STYLE_HIDDEN) : (pControl->dwInternalStyle & ~INTERNAL_CONTROL_STYLE_HIDDEN); | 1347 | pControl->dwInternalStyle = (SW_HIDE == nCmdShow) ? (pControl->dwInternalStyle | INTERNAL_CONTROL_STYLE_HIDDEN) : (pControl->dwInternalStyle & ~INTERNAL_CONTROL_STYLE_HIDDEN); |
1370 | } | 1348 | } |
1371 | } | 1349 | } |
1372 | 1350 | ||
1373 | 1351 | ||
1374 | DAPI_(void) ThemeShowControlEx( | 1352 | DAPI_(void) ThemeShowControlEx( |
1375 | __in THEME* pTheme, | 1353 | __in const THEME_CONTROL* pThemeControl, |
1376 | __in DWORD dwControl, | ||
1377 | __in int nCmdShow | 1354 | __in int nCmdShow |
1378 | ) | 1355 | ) |
1379 | { | 1356 | { |
1380 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1357 | if (pThemeControl) |
1381 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd)); | ||
1382 | if (pControl) | ||
1383 | { | 1358 | { |
1384 | ShowControl(pTheme, pControl, nCmdShow, THEME_CONTROL_TYPE_EDITBOX == pControl->type, THEME_SHOW_PAGE_REASON_REFRESH, 0, NULL); | 1359 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl); |
1360 | ShowControl(pControl, nCmdShow, THEME_CONTROL_TYPE_EDITBOX == pControl->type, THEME_SHOW_PAGE_REASON_REFRESH, 0, NULL); | ||
1385 | } | 1361 | } |
1386 | } | 1362 | } |
1387 | 1363 | ||
1388 | 1364 | ||
1389 | DAPI_(BOOL) ThemeControlVisible( | 1365 | DAPI_(BOOL) ThemeControlVisible( |
1390 | __in THEME* pTheme, | 1366 | __in const THEME_CONTROL* pThemeControl |
1391 | __in DWORD dwControl | ||
1392 | ) | 1367 | ) |
1393 | { | 1368 | { |
1394 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1369 | BOOL fVisible = FALSE; |
1395 | return ::IsWindowVisible(hWnd); | ||
1396 | } | ||
1397 | |||
1398 | 1370 | ||
1399 | DAPI_(BOOL) ThemePostControlMessage( | 1371 | if (pThemeControl) |
1400 | __in THEME* pTheme, | ||
1401 | __in DWORD dwControl, | ||
1402 | __in UINT Msg, | ||
1403 | __in WPARAM wParam, | ||
1404 | __in LPARAM lParam | ||
1405 | ) | ||
1406 | { | ||
1407 | HRESULT hr = S_OK; | ||
1408 | UINT er = ERROR_SUCCESS; | ||
1409 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | ||
1410 | |||
1411 | if (!::PostMessageW(hWnd, Msg, wParam, lParam)) | ||
1412 | { | 1372 | { |
1413 | er = ::GetLastError(); | 1373 | fVisible = ::IsWindowVisible(pThemeControl->hWnd); |
1414 | hr = HRESULT_FROM_WIN32(er); | ||
1415 | } | 1374 | } |
1416 | 1375 | ||
1417 | return SUCCEEDED(hr); | 1376 | return fVisible; |
1418 | } | ||
1419 | |||
1420 | |||
1421 | DAPI_(LRESULT) ThemeSendControlMessage( | ||
1422 | __in const THEME* pTheme, | ||
1423 | __in DWORD dwControl, | ||
1424 | __in UINT Msg, | ||
1425 | __in WPARAM wParam, | ||
1426 | __in LPARAM lParam | ||
1427 | ) | ||
1428 | { | ||
1429 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | ||
1430 | return ::SendMessageW(hWnd, Msg, wParam, lParam); | ||
1431 | } | 1377 | } |
1432 | 1378 | ||
1433 | 1379 | ||
@@ -1453,9 +1399,15 @@ DAPI_(HRESULT) ThemeDrawControl( | |||
1453 | ) | 1399 | ) |
1454 | { | 1400 | { |
1455 | HRESULT hr = S_OK; | 1401 | HRESULT hr = S_OK; |
1456 | const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, pdis->hwndItem); | 1402 | const THEME_CONTROL* pControl = NULL; |
1403 | BOOL fExists = ThemeControlExistsByHWnd(pTheme, pdis->hwndItem, &pControl); | ||
1404 | |||
1405 | AssertSz(fExists, "Expected control window from owner draw window."); | ||
1406 | if (!fExists) | ||
1407 | { | ||
1408 | ExitFunction1(hr = E_INVALIDARG); | ||
1409 | } | ||
1457 | 1410 | ||
1458 | AssertSz(pControl, "Expected control window from owner draw window."); | ||
1459 | AssertSz(pControl->hWnd == pdis->hwndItem, "Expected control window to match owner draw window."); | 1411 | AssertSz(pControl->hWnd == pdis->hwndItem, "Expected control window to match owner draw window."); |
1460 | AssertSz(pControl->nWidth < 1 || pControl->nWidth == pdis->rcItem.right - pdis->rcItem.left, "Expected control window width to match owner draw window width."); | 1412 | AssertSz(pControl->nWidth < 1 || pControl->nWidth == pdis->rcItem.right - pdis->rcItem.left, "Expected control window width to match owner draw window width."); |
1461 | AssertSz(pControl->nHeight < 1 || pControl->nHeight == pdis->rcItem.bottom - pdis->rcItem.top, "Expected control window height to match owner draw window height."); | 1413 | AssertSz(pControl->nHeight < 1 || pControl->nHeight == pdis->rcItem.bottom - pdis->rcItem.top, "Expected control window height to match owner draw window height."); |
@@ -1492,7 +1444,7 @@ LExit: | |||
1492 | } | 1444 | } |
1493 | 1445 | ||
1494 | 1446 | ||
1495 | DAPI_(BOOL) ThemeHoverControl( | 1447 | static BOOL ThemeHoverControl( |
1496 | __in THEME* pTheme, | 1448 | __in THEME* pTheme, |
1497 | __in HWND hwndParent, | 1449 | __in HWND hwndParent, |
1498 | __in HWND hwndControl | 1450 | __in HWND hwndControl |
@@ -1519,16 +1471,21 @@ DAPI_(BOOL) ThemeHoverControl( | |||
1519 | 1471 | ||
1520 | 1472 | ||
1521 | DAPI_(BOOL) ThemeIsControlChecked( | 1473 | DAPI_(BOOL) ThemeIsControlChecked( |
1522 | __in THEME* pTheme, | 1474 | __in const THEME_CONTROL* pThemeControl |
1523 | __in DWORD dwControl | ||
1524 | ) | 1475 | ) |
1525 | { | 1476 | { |
1526 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1477 | BOOL fChecked = FALSE; |
1527 | return BST_CHECKED == ::SendMessageW(hWnd, BM_GETCHECK, 0, 0); | 1478 | |
1479 | if (pThemeControl) | ||
1480 | { | ||
1481 | fChecked = BST_CHECKED == ::SendMessageW(pThemeControl->hWnd, BM_GETCHECK, 0, 0); | ||
1482 | } | ||
1483 | |||
1484 | return fChecked; | ||
1528 | } | 1485 | } |
1529 | 1486 | ||
1530 | 1487 | ||
1531 | DAPI_(BOOL) ThemeSetControlColor( | 1488 | static BOOL ThemeSetControlColor( |
1532 | __in THEME* pTheme, | 1489 | __in THEME* pTheme, |
1533 | __in HDC hdc, | 1490 | __in HDC hdc, |
1534 | __in HWND hWnd, | 1491 | __in HWND hWnd, |
@@ -1537,6 +1494,7 @@ DAPI_(BOOL) ThemeSetControlColor( | |||
1537 | { | 1494 | { |
1538 | THEME_FONT* pFont = NULL; | 1495 | THEME_FONT* pFont = NULL; |
1539 | BOOL fHasBackground = FALSE; | 1496 | BOOL fHasBackground = FALSE; |
1497 | const THEME_CONTROL* pControl = NULL; | ||
1540 | 1498 | ||
1541 | *phBackgroundBrush = NULL; | 1499 | *phBackgroundBrush = NULL; |
1542 | 1500 | ||
@@ -1544,10 +1502,9 @@ DAPI_(BOOL) ThemeSetControlColor( | |||
1544 | { | 1502 | { |
1545 | pFont = (THEME_INVALID_ID == pTheme->dwFontId) ? NULL : pTheme->rgFonts + pTheme->dwFontId; | 1503 | pFont = (THEME_INVALID_ID == pTheme->dwFontId) ? NULL : pTheme->rgFonts + pTheme->dwFontId; |
1546 | } | 1504 | } |
1547 | else | 1505 | else if (ThemeControlExistsByHWnd(pTheme, hWnd, &pControl)) |
1548 | { | 1506 | { |
1549 | const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd); | 1507 | pFont = THEME_INVALID_ID == pControl->dwFontId ? NULL : pTheme->rgFonts + pControl->dwFontId; |
1550 | pFont = (!pControl || THEME_INVALID_ID == pControl->dwFontId) ? NULL : pTheme->rgFonts + pControl->dwFontId; | ||
1551 | } | 1508 | } |
1552 | 1509 | ||
1553 | if (pFont) | 1510 | if (pFont) |
@@ -1577,44 +1534,40 @@ DAPI_(BOOL) ThemeSetControlColor( | |||
1577 | 1534 | ||
1578 | 1535 | ||
1579 | DAPI_(HRESULT) ThemeSetProgressControl( | 1536 | DAPI_(HRESULT) ThemeSetProgressControl( |
1580 | __in THEME* pTheme, | 1537 | __in const THEME_CONTROL* pThemeControl, |
1581 | __in DWORD dwControl, | ||
1582 | __in DWORD dwProgressPercentage | 1538 | __in DWORD dwProgressPercentage |
1583 | ) | 1539 | ) |
1584 | { | 1540 | { |
1585 | HRESULT hr = E_NOTFOUND; | 1541 | HRESULT hr = E_INVALIDARG; |
1586 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | ||
1587 | 1542 | ||
1588 | if (hWnd) | 1543 | if (pThemeControl && THEME_CONTROL_TYPE_PROGRESSBAR == pThemeControl->type) |
1589 | { | 1544 | { |
1590 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd)); | 1545 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl); |
1591 | if (pControl && THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type) | 1546 | |
1547 | DWORD dwCurrentProgress = LOWORD(pControl->dwData); | ||
1548 | |||
1549 | if (dwCurrentProgress != dwProgressPercentage) | ||
1592 | { | 1550 | { |
1593 | DWORD dwCurrentProgress = LOWORD(pControl->dwData); | 1551 | DWORD dwColor = HIWORD(pControl->dwData); |
1552 | pControl->dwData = MAKEDWORD(dwProgressPercentage, dwColor); | ||
1594 | 1553 | ||
1595 | if (dwCurrentProgress != dwProgressPercentage) | 1554 | if (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW) |
1596 | { | 1555 | { |
1597 | DWORD dwColor = HIWORD(pControl->dwData); | 1556 | if (!::InvalidateRect(pControl->hWnd, NULL, FALSE)) |
1598 | pControl->dwData = MAKEDWORD(dwProgressPercentage, dwColor); | ||
1599 | |||
1600 | if (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW) | ||
1601 | { | 1557 | { |
1602 | if (!::InvalidateRect(hWnd, NULL, FALSE)) | 1558 | ThmExitWithLastError(hr, "Failed to invalidate progress bar window."); |
1603 | { | ||
1604 | ThmExitWithLastError(hr, "Failed to invalidate progress bar window."); | ||
1605 | } | ||
1606 | } | ||
1607 | else | ||
1608 | { | ||
1609 | ::SendMessageW(hWnd, PBM_SETPOS, dwProgressPercentage, 0); | ||
1610 | } | 1559 | } |
1611 | |||
1612 | hr = S_OK; | ||
1613 | } | 1560 | } |
1614 | else | 1561 | else |
1615 | { | 1562 | { |
1616 | hr = S_FALSE; | 1563 | ::SendMessageW(pControl->hWnd, PBM_SETPOS, dwProgressPercentage, 0); |
1617 | } | 1564 | } |
1565 | |||
1566 | hr = S_OK; | ||
1567 | } | ||
1568 | else | ||
1569 | { | ||
1570 | hr = S_FALSE; | ||
1618 | } | 1571 | } |
1619 | } | 1572 | } |
1620 | 1573 | ||
@@ -1624,37 +1577,37 @@ LExit: | |||
1624 | 1577 | ||
1625 | 1578 | ||
1626 | DAPI_(HRESULT) ThemeSetProgressControlColor( | 1579 | DAPI_(HRESULT) ThemeSetProgressControlColor( |
1627 | __in THEME* pTheme, | 1580 | __in const THEME_CONTROL* pThemeControl, |
1628 | __in DWORD dwControl, | ||
1629 | __in DWORD dwColorIndex | 1581 | __in DWORD dwColorIndex |
1630 | ) | 1582 | ) |
1631 | { | 1583 | { |
1632 | HRESULT hr = S_FALSE; | 1584 | HRESULT hr = E_INVALIDARG; |
1633 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1585 | |
1634 | if (hWnd) | 1586 | // Only set color on owner draw progress bars. |
1587 | if (pThemeControl && THEME_CONTROL_TYPE_PROGRESSBAR == pThemeControl->type && (pThemeControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW)) | ||
1635 | { | 1588 | { |
1636 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd)); | 1589 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(pThemeControl); |
1637 | 1590 | ||
1638 | // Only set color on owner draw progress bars. | 1591 | if (pControl->ProgressBar.cImageRef <= dwColorIndex) |
1639 | if (pControl && (pControl->dwInternalStyle & INTERNAL_CONTROL_STYLE_OWNER_DRAW) && THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type) | ||
1640 | { | 1592 | { |
1641 | if (pControl->ProgressBar.cImageRef <= dwColorIndex) | 1593 | ThmExitWithRootFailure(hr, E_INVALIDARG, "Invalid progress bar color index: %u", dwColorIndex); |
1642 | { | 1594 | } |
1643 | ThmExitWithRootFailure(hr, E_INVALIDARG, "Invalid progress bar color index: %u", dwColorIndex); | ||
1644 | } | ||
1645 | |||
1646 | if (HIWORD(pControl->dwData) != dwColorIndex) | ||
1647 | { | ||
1648 | DWORD dwCurrentProgress = LOWORD(pControl->dwData); | ||
1649 | pControl->dwData = MAKEDWORD(dwCurrentProgress, dwColorIndex); | ||
1650 | 1595 | ||
1651 | if (!::InvalidateRect(hWnd, NULL, FALSE)) | 1596 | if (HIWORD(pControl->dwData) != dwColorIndex) |
1652 | { | 1597 | { |
1653 | ThmExitWithLastError(hr, "Failed to invalidate progress bar window."); | 1598 | DWORD dwCurrentProgress = LOWORD(pControl->dwData); |
1654 | } | 1599 | pControl->dwData = MAKEDWORD(dwCurrentProgress, dwColorIndex); |
1655 | 1600 | ||
1656 | hr = S_OK; | 1601 | if (!::InvalidateRect(pControl->hWnd, NULL, FALSE)) |
1602 | { | ||
1603 | ThmExitWithLastError(hr, "Failed to invalidate progress bar window."); | ||
1657 | } | 1604 | } |
1605 | |||
1606 | hr = S_OK; | ||
1607 | } | ||
1608 | else | ||
1609 | { | ||
1610 | hr = S_FALSE; | ||
1658 | } | 1611 | } |
1659 | } | 1612 | } |
1660 | 1613 | ||
@@ -1664,41 +1617,40 @@ LExit: | |||
1664 | 1617 | ||
1665 | 1618 | ||
1666 | DAPI_(HRESULT) ThemeSetTextControl( | 1619 | DAPI_(HRESULT) ThemeSetTextControl( |
1667 | __in const THEME* pTheme, | 1620 | __in const THEME_CONTROL* pThemeControl, |
1668 | __in DWORD dwControl, | ||
1669 | __in_z_opt LPCWSTR wzText | 1621 | __in_z_opt LPCWSTR wzText |
1670 | ) | 1622 | ) |
1671 | { | 1623 | { |
1672 | return ThemeSetTextControlEx(pTheme, dwControl, FALSE, wzText); | 1624 | return ThemeSetTextControlEx(pThemeControl, FALSE, wzText); |
1673 | } | 1625 | } |
1674 | 1626 | ||
1675 | 1627 | ||
1676 | DAPI_(HRESULT) ThemeSetTextControlEx( | 1628 | DAPI_(HRESULT) ThemeSetTextControlEx( |
1677 | __in const THEME* pTheme, | 1629 | __in const THEME_CONTROL* pThemeControl, |
1678 | __in DWORD dwControl, | ||
1679 | __in BOOL fUpdate, | 1630 | __in BOOL fUpdate, |
1680 | __in_z_opt LPCWSTR wzText | 1631 | __in_z_opt LPCWSTR wzText |
1681 | ) | 1632 | ) |
1682 | { | 1633 | { |
1683 | HRESULT hr = S_OK; | 1634 | HRESULT hr = E_INVALIDARG; |
1684 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | ||
1685 | 1635 | ||
1686 | if (hWnd) | 1636 | if (pThemeControl) |
1687 | { | 1637 | { |
1688 | if (fUpdate) | 1638 | if (fUpdate) |
1689 | { | 1639 | { |
1690 | ::ShowWindow(hWnd, SW_HIDE); | 1640 | ::ShowWindow(pThemeControl->hWnd, SW_HIDE); |
1691 | } | 1641 | } |
1692 | 1642 | ||
1693 | if (!::SetWindowTextW(hWnd, wzText)) | 1643 | if (!::SetWindowTextW(pThemeControl->hWnd, wzText)) |
1694 | { | 1644 | { |
1695 | ThmExitWithLastError(hr, "Failed to set control text."); | 1645 | ThmExitWithLastError(hr, "Failed to set control text."); |
1696 | } | 1646 | } |
1697 | 1647 | ||
1698 | if (fUpdate) | 1648 | if (fUpdate) |
1699 | { | 1649 | { |
1700 | ::ShowWindow(hWnd, SW_SHOW); | 1650 | ::ShowWindow(pThemeControl->hWnd, SW_SHOW); |
1701 | } | 1651 | } |
1652 | |||
1653 | hr = S_OK; | ||
1702 | } | 1654 | } |
1703 | 1655 | ||
1704 | LExit: | 1656 | LExit: |
@@ -1707,50 +1659,17 @@ LExit: | |||
1707 | 1659 | ||
1708 | 1660 | ||
1709 | DAPI_(HRESULT) ThemeGetTextControl( | 1661 | DAPI_(HRESULT) ThemeGetTextControl( |
1710 | __in const THEME* pTheme, | 1662 | __in const THEME_CONTROL* pThemeControl, |
1711 | __in DWORD dwControl, | ||
1712 | __inout_z LPWSTR* psczText | 1663 | __inout_z LPWSTR* psczText |
1713 | ) | 1664 | ) |
1714 | { | 1665 | { |
1715 | HRESULT hr = S_OK; | 1666 | HRESULT hr = E_INVALIDARG; |
1716 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | ||
1717 | SIZE_T cbSize = 0; | ||
1718 | DWORD cchText = 0; | ||
1719 | DWORD cchTextRead = 0; | ||
1720 | |||
1721 | // Ensure the string has room for at least one character. | ||
1722 | hr = StrMaxLength(*psczText, &cbSize); | ||
1723 | ThmExitOnFailure(hr, "Failed to get text buffer length."); | ||
1724 | 1667 | ||
1725 | cchText = (DWORD)min(DWORD_MAX, cbSize); | 1668 | if (pThemeControl) |
1726 | |||
1727 | if (!cchText) | ||
1728 | { | 1669 | { |
1729 | cchText = GROW_WINDOW_TEXT; | 1670 | hr = WnduGetControlText(pThemeControl->hWnd, psczText); |
1730 | |||
1731 | hr = StrAlloc(psczText, cchText); | ||
1732 | ThmExitOnFailure(hr, "Failed to grow text buffer."); | ||
1733 | } | 1671 | } |
1734 | 1672 | ||
1735 | // Read (and keep growing buffer) until we finally read less than there | ||
1736 | // is room in the buffer. | ||
1737 | for (;;) | ||
1738 | { | ||
1739 | cchTextRead = ::GetWindowTextW(hWnd, *psczText, cchText); | ||
1740 | if (cchTextRead + 1 < cchText) | ||
1741 | { | ||
1742 | break; | ||
1743 | } | ||
1744 | else | ||
1745 | { | ||
1746 | cchText = cchTextRead + GROW_WINDOW_TEXT; | ||
1747 | |||
1748 | hr = StrAlloc(psczText, cchText); | ||
1749 | ThmExitOnFailure(hr, "Failed to grow text buffer again."); | ||
1750 | } | ||
1751 | } | ||
1752 | |||
1753 | LExit: | ||
1754 | return hr; | 1673 | return hr; |
1755 | } | 1674 | } |
1756 | 1675 | ||
@@ -1771,25 +1690,26 @@ LExit: | |||
1771 | 1690 | ||
1772 | 1691 | ||
1773 | DAPI_(void) ThemeSetFocus( | 1692 | DAPI_(void) ThemeSetFocus( |
1774 | __in THEME* pTheme, | 1693 | __in const THEME_CONTROL* pThemeControl |
1775 | __in DWORD dwControl | ||
1776 | ) | 1694 | ) |
1777 | { | 1695 | { |
1778 | HWND hwndFocus = ::GetDlgItem(pTheme->hwndParent, dwControl); | 1696 | if (pThemeControl) |
1779 | if (hwndFocus && !ThemeControlEnabled(pTheme, dwControl)) | 1697 | { |
1780 | { | 1698 | HWND hwndFocus = pThemeControl->hWnd; |
1781 | hwndFocus = ::GetNextDlgTabItem(pTheme->hwndParent, hwndFocus, FALSE); | 1699 | if (hwndFocus && !ThemeControlEnabled(pThemeControl)) |
1782 | } | 1700 | { |
1701 | hwndFocus = ::GetNextDlgTabItem(pThemeControl->pTheme->hwndParent, hwndFocus, FALSE); | ||
1702 | } | ||
1783 | 1703 | ||
1784 | if (hwndFocus) | 1704 | if (hwndFocus) |
1785 | { | 1705 | { |
1786 | ::SetFocus(hwndFocus); | 1706 | ::SetFocus(hwndFocus); |
1707 | } | ||
1787 | } | 1708 | } |
1788 | } | 1709 | } |
1789 | 1710 | ||
1790 | 1711 | ||
1791 | DAPI_(void) ThemeShowChild( | 1712 | DAPI_(void) ThemeShowChild( |
1792 | __in THEME* pTheme, | ||
1793 | __in THEME_CONTROL* pParentControl, | 1713 | __in THEME_CONTROL* pParentControl, |
1794 | __in DWORD dwIndex | 1714 | __in DWORD dwIndex |
1795 | ) | 1715 | ) |
@@ -1798,7 +1718,7 @@ DAPI_(void) ThemeShowChild( | |||
1798 | for (DWORD i = 0; i < pParentControl->cControls; ++i) | 1718 | for (DWORD i = 0; i < pParentControl->cControls; ++i) |
1799 | { | 1719 | { |
1800 | THEME_CONTROL* pControl = pParentControl->rgControls + i; | 1720 | THEME_CONTROL* pControl = pParentControl->rgControls + i; |
1801 | ShowControl(pTheme, pControl, dwIndex == i ? SW_SHOW : SW_HIDE, FALSE, THEME_SHOW_PAGE_REASON_DEFAULT, 0, NULL); | 1721 | ShowControl(pControl, dwIndex == i ? SW_SHOW : SW_HIDE, FALSE, THEME_SHOW_PAGE_REASON_DEFAULT, 0, NULL); |
1802 | } | 1722 | } |
1803 | } | 1723 | } |
1804 | 1724 | ||
@@ -4322,28 +4242,24 @@ LExit: | |||
4322 | 4242 | ||
4323 | static HRESULT StartBillboard( | 4243 | static HRESULT StartBillboard( |
4324 | __in THEME* pTheme, | 4244 | __in THEME* pTheme, |
4325 | __in DWORD dwControl | 4245 | __in THEME_CONTROL* pControl |
4326 | ) | 4246 | ) |
4327 | { | 4247 | { |
4328 | HRESULT hr = E_NOTFOUND; | 4248 | HRESULT hr = E_NOTFOUND; |
4329 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 4249 | UINT_PTR idEvent = reinterpret_cast<UINT_PTR>(pControl); |
4330 | 4250 | ||
4331 | if (hWnd) | 4251 | if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type) |
4332 | { | 4252 | { |
4333 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hWnd)); | 4253 | // kick off |
4334 | if (pControl && THEME_CONTROL_TYPE_BILLBOARD == pControl->type) | 4254 | pControl->dwData = 0; |
4335 | { | 4255 | OnBillboardTimer(pTheme, pTheme->hwndParent, idEvent); |
4336 | // kick off | ||
4337 | pControl->dwData = 0; | ||
4338 | OnBillboardTimer(pTheme, pTheme->hwndParent, dwControl); | ||
4339 | 4256 | ||
4340 | if (!::SetTimer(pTheme->hwndParent, pControl->wId, pControl->wBillboardInterval, NULL)) | 4257 | if (!::SetTimer(pTheme->hwndParent, idEvent, pControl->wBillboardInterval, NULL)) |
4341 | { | 4258 | { |
4342 | ThmExitWithLastError(hr, "Failed to start billboard."); | 4259 | ThmExitWithLastError(hr, "Failed to start billboard."); |
4343 | } | ||
4344 | |||
4345 | hr = S_OK; | ||
4346 | } | 4260 | } |
4261 | |||
4262 | hr = S_OK; | ||
4347 | } | 4263 | } |
4348 | 4264 | ||
4349 | LExit: | 4265 | LExit: |
@@ -4353,23 +4269,19 @@ LExit: | |||
4353 | 4269 | ||
4354 | static HRESULT StopBillboard( | 4270 | static HRESULT StopBillboard( |
4355 | __in THEME* pTheme, | 4271 | __in THEME* pTheme, |
4356 | __in DWORD dwControl | 4272 | __in THEME_CONTROL* pControl |
4357 | ) | 4273 | ) |
4358 | { | 4274 | { |
4359 | HRESULT hr = E_NOTFOUND; | 4275 | HRESULT hr = E_NOTFOUND; |
4360 | HWND hWnd = ::GetDlgItem(pTheme->hwndParent, dwControl); | 4276 | UINT_PTR idEvent = reinterpret_cast<UINT_PTR>(pControl); |
4361 | 4277 | ||
4362 | if (hWnd) | 4278 | if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type) |
4363 | { | 4279 | { |
4364 | const THEME_CONTROL* pControl = FindControlFromHWnd(pTheme, hWnd); | 4280 | ThemeControlEnable(pControl, FALSE); |
4365 | if (pControl && THEME_CONTROL_TYPE_BILLBOARD == pControl->type) | ||
4366 | { | ||
4367 | ThemeControlEnable(pTheme, dwControl, FALSE); | ||
4368 | 4281 | ||
4369 | if (::KillTimer(pTheme->hwndParent, pControl->wId)) | 4282 | if (::KillTimer(pTheme->hwndParent, idEvent)) |
4370 | { | 4283 | { |
4371 | hr = S_OK; | 4284 | hr = S_OK; |
4372 | } | ||
4373 | } | 4285 | } |
4374 | } | 4286 | } |
4375 | 4287 | ||
@@ -5039,81 +4951,33 @@ static void FreeImageInstance( | |||
5039 | } | 4951 | } |
5040 | 4952 | ||
5041 | 4953 | ||
5042 | static DWORD CALLBACK RichEditStreamFromFileHandleCallback( | ||
5043 | __in DWORD_PTR dwCookie, | ||
5044 | __in_bcount(cb) LPBYTE pbBuff, | ||
5045 | __in LONG cb, | ||
5046 | __in LONG* pcb | ||
5047 | ) | ||
5048 | { | ||
5049 | HRESULT hr = S_OK; | ||
5050 | HANDLE hFile = reinterpret_cast<HANDLE>(dwCookie); | ||
5051 | |||
5052 | if (!::ReadFile(hFile, pbBuff, cb, reinterpret_cast<DWORD*>(pcb), NULL)) | ||
5053 | { | ||
5054 | ThmExitWithLastError(hr, "Failed to read file"); | ||
5055 | } | ||
5056 | |||
5057 | LExit: | ||
5058 | return hr; | ||
5059 | } | ||
5060 | |||
5061 | |||
5062 | static DWORD CALLBACK RichEditStreamFromMemoryCallback( | ||
5063 | __in DWORD_PTR dwCookie, | ||
5064 | __in_bcount(cb) LPBYTE pbBuff, | ||
5065 | __in LONG cb, | ||
5066 | __in LONG* pcb | ||
5067 | ) | ||
5068 | { | ||
5069 | HRESULT hr = S_OK; | ||
5070 | MEMBUFFER_FOR_RICHEDIT* pBuffer = reinterpret_cast<MEMBUFFER_FOR_RICHEDIT*>(dwCookie); | ||
5071 | DWORD cbCopy = 0; | ||
5072 | |||
5073 | if (pBuffer->iData < pBuffer->cbData) | ||
5074 | { | ||
5075 | cbCopy = min(static_cast<DWORD>(cb), pBuffer->cbData - pBuffer->iData); | ||
5076 | memcpy(pbBuff, pBuffer->rgbData + pBuffer->iData, cbCopy); | ||
5077 | |||
5078 | pBuffer->iData += cbCopy; | ||
5079 | Assert(pBuffer->iData <= pBuffer->cbData); | ||
5080 | } | ||
5081 | |||
5082 | *pcb = cbCopy; | ||
5083 | return hr; | ||
5084 | } | ||
5085 | |||
5086 | |||
5087 | static void CALLBACK OnBillboardTimer( | 4954 | static void CALLBACK OnBillboardTimer( |
5088 | __in THEME* pTheme, | 4955 | __in THEME* /*pTheme*/, |
5089 | __in HWND hwnd, | 4956 | __in HWND hwnd, |
5090 | __in UINT_PTR idEvent | 4957 | __in UINT_PTR idEvent |
5091 | ) | 4958 | ) |
5092 | { | 4959 | { |
5093 | HWND hwndControl = ::GetDlgItem(hwnd, static_cast<int>(idEvent)); | 4960 | THEME_CONTROL* pControl = reinterpret_cast<THEME_CONTROL*>(idEvent); |
5094 | if (hwndControl) | 4961 | |
4962 | if (pControl) | ||
5095 | { | 4963 | { |
5096 | THEME_CONTROL* pControl = const_cast<THEME_CONTROL*>(FindControlFromHWnd(pTheme, hwndControl)); | 4964 | AssertSz(THEME_CONTROL_TYPE_BILLBOARD == pControl->type, "Only billboard controls should get billboard timer messages."); |
5097 | AssertSz(pControl && THEME_CONTROL_TYPE_BILLBOARD == pControl->type, "Only billboard controls should get billboard timer messages."); | ||
5098 | 4965 | ||
5099 | if (pControl) | 4966 | if (pControl->dwData < pControl->cControls) |
5100 | { | 4967 | { |
5101 | if (pControl->dwData < pControl->cControls) | 4968 | ThemeShowChild(pControl, pControl->dwData); |
5102 | { | ||
5103 | ThemeShowChild(pTheme, pControl, pControl->dwData); | ||
5104 | } | ||
5105 | else if (pControl->fBillboardLoops) | ||
5106 | { | ||
5107 | pControl->dwData = 0; | ||
5108 | ThemeShowChild(pTheme, pControl, pControl->dwData); | ||
5109 | } | ||
5110 | else // no more looping | ||
5111 | { | ||
5112 | ::KillTimer(hwnd, idEvent); | ||
5113 | } | ||
5114 | |||
5115 | ++pControl->dwData; | ||
5116 | } | 4969 | } |
4970 | else if (pControl->fBillboardLoops) | ||
4971 | { | ||
4972 | pControl->dwData = 0; | ||
4973 | ThemeShowChild(pControl, pControl->dwData); | ||
4974 | } | ||
4975 | else // no more looping | ||
4976 | { | ||
4977 | ::KillTimer(hwnd, idEvent); | ||
4978 | } | ||
4979 | |||
4980 | ++pControl->dwData; | ||
5117 | } | 4981 | } |
5118 | } | 4982 | } |
5119 | 4983 | ||
@@ -5151,7 +5015,7 @@ static void OnBrowseDirectory( | |||
5151 | 5015 | ||
5152 | if (pTargetControl && THEME_CONTROL_TYPE_EDITBOX == pTargetControl->type && !pTargetControl->fDisableVariableFunctionality) | 5016 | if (pTargetControl && THEME_CONTROL_TYPE_EDITBOX == pTargetControl->type && !pTargetControl->fDisableVariableFunctionality) |
5153 | { | 5017 | { |
5154 | hr = ThemeSetTextControl(pTheme, pTargetControl->wId, wzPath); | 5018 | hr = ThemeSetTextControl(pTargetControl, wzPath); |
5155 | ThmExitOnFailure(hr, "Failed to set text on editbox: %ls", pTargetControl->sczName); | 5019 | ThmExitOnFailure(hr, "Failed to set text on editbox: %ls", pTargetControl->sczName); |
5156 | } | 5020 | } |
5157 | else if (pTheme->pfnSetStringVariable) | 5021 | else if (pTheme->pfnSetStringVariable) |
@@ -5161,7 +5025,7 @@ static void OnBrowseDirectory( | |||
5161 | } | 5025 | } |
5162 | else if (pTargetControl) | 5026 | else if (pTargetControl) |
5163 | { | 5027 | { |
5164 | hr = ThemeSetTextControl(pTheme, pTargetControl->wId, wzPath); | 5028 | hr = ThemeSetTextControl(pTargetControl, wzPath); |
5165 | ThmExitOnFailure(hr, "Failed to set text on control: %ls", pTargetControl->sczName); | 5029 | ThmExitOnFailure(hr, "Failed to set text on control: %ls", pTargetControl->sczName); |
5166 | } | 5030 | } |
5167 | 5031 | ||
@@ -5252,13 +5116,13 @@ static BOOL OnButtonClicked( | |||
5252 | case THEME_CONTROL_TYPE_CHECKBOX: | 5116 | case THEME_CONTROL_TYPE_CHECKBOX: |
5253 | if (pTheme->pfnSetNumericVariable && pControl->sczName && *pControl->sczName) | 5117 | if (pTheme->pfnSetNumericVariable && pControl->sczName && *pControl->sczName) |
5254 | { | 5118 | { |
5255 | BOOL fChecked = ThemeIsControlChecked(pTheme, pControl->wId); | 5119 | BOOL fChecked = ThemeIsControlChecked(pControl); |
5256 | pTheme->pfnSetNumericVariable(pControl->sczName, fChecked ? 1 : 0, pTheme->pvVariableContext); | 5120 | pTheme->pfnSetNumericVariable(pControl->sczName, fChecked ? 1 : 0, pTheme->pvVariableContext); |
5257 | fRefresh = TRUE; | 5121 | fRefresh = TRUE; |
5258 | } | 5122 | } |
5259 | break; | 5123 | break; |
5260 | case THEME_CONTROL_TYPE_RADIOBUTTON: | 5124 | case THEME_CONTROL_TYPE_RADIOBUTTON: |
5261 | if (pTheme->pfnSetStringVariable && pControl->sczVariable && *pControl->sczVariable && ThemeIsControlChecked(pTheme, pControl->wId)) | 5125 | if (pTheme->pfnSetStringVariable && pControl->sczVariable && *pControl->sczVariable && ThemeIsControlChecked(pControl)) |
5262 | { | 5126 | { |
5263 | pTheme->pfnSetStringVariable(pControl->sczVariable, pControl->sczValue, FALSE, pTheme->pvVariableContext); | 5127 | pTheme->pfnSetStringVariable(pControl->sczVariable, pControl->sczValue, FALSE, pTheme->pvVariableContext); |
5264 | fRefresh = TRUE; | 5128 | fRefresh = TRUE; |
@@ -5386,6 +5250,42 @@ LExit: | |||
5386 | return fProcessed; | 5250 | return fProcessed; |
5387 | } | 5251 | } |
5388 | 5252 | ||
5253 | static const THEME_CONTROL* FindControlFromId( | ||
5254 | __in const THEME* pTheme, | ||
5255 | __in WORD wId, | ||
5256 | __in_opt const THEME_CONTROL* pParentControl | ||
5257 | ) | ||
5258 | { | ||
5259 | DWORD cControls = 0; | ||
5260 | THEME_CONTROL* rgControls = NULL; | ||
5261 | const THEME_CONTROL* pChildControl = NULL; | ||
5262 | |||
5263 | GetControls(pTheme, pParentControl, cControls, rgControls); | ||
5264 | |||
5265 | // Breadth first search since control ids are technically only valid for direct child windows of a specific parent window. | ||
5266 | for (DWORD i = 0; i < cControls; ++i) | ||
5267 | { | ||
5268 | if (wId == rgControls[i].wId) | ||
5269 | { | ||
5270 | return rgControls + i; | ||
5271 | } | ||
5272 | } | ||
5273 | |||
5274 | for (DWORD i = 0; i < cControls; ++i) | ||
5275 | { | ||
5276 | if (0 < rgControls[i].cControls) | ||
5277 | { | ||
5278 | pChildControl = FindControlFromId(pTheme, wId, rgControls + i); | ||
5279 | if (pChildControl) | ||
5280 | { | ||
5281 | return pChildControl; | ||
5282 | } | ||
5283 | } | ||
5284 | } | ||
5285 | |||
5286 | return NULL; | ||
5287 | } | ||
5288 | |||
5389 | static BOOL OnNotifyEnMsgFilter( | 5289 | static BOOL OnNotifyEnMsgFilter( |
5390 | __in THEME* pTheme, | 5290 | __in THEME* pTheme, |
5391 | __in const THEME_CONTROL* pThemeControl, | 5291 | __in const THEME_CONTROL* pThemeControl, |
@@ -5638,7 +5538,6 @@ LExit: | |||
5638 | 5538 | ||
5639 | 5539 | ||
5640 | static HRESULT ShowControl( | 5540 | static HRESULT ShowControl( |
5641 | __in THEME* pTheme, | ||
5642 | __in THEME_CONTROL* pControl, | 5541 | __in THEME_CONTROL* pControl, |
5643 | __in int nCmdShow, | 5542 | __in int nCmdShow, |
5644 | __in BOOL fSaveEditboxes, | 5543 | __in BOOL fSaveEditboxes, |
@@ -5654,13 +5553,14 @@ static HRESULT ShowControl( | |||
5654 | LPWSTR sczText = NULL; | 5553 | LPWSTR sczText = NULL; |
5655 | THEME_SAVEDVARIABLE* pSavedVariable = NULL; | 5554 | THEME_SAVEDVARIABLE* pSavedVariable = NULL; |
5656 | BOOL fHide = SW_HIDE == nCmdShow; | 5555 | BOOL fHide = SW_HIDE == nCmdShow; |
5556 | THEME* pTheme = pControl->pTheme; | ||
5657 | THEME_PAGE* pPage = ThemeGetPage(pTheme, dwPageId); | 5557 | THEME_PAGE* pPage = ThemeGetPage(pTheme, dwPageId); |
5658 | 5558 | ||
5659 | // Save the editbox value if necessary (other control types save their values immediately). | 5559 | // Save the editbox value if necessary (other control types save their values immediately). |
5660 | if (pTheme->pfnSetStringVariable && !pControl->fDisableVariableFunctionality && | 5560 | if (pTheme->pfnSetStringVariable && !pControl->fDisableVariableFunctionality && |
5661 | fSaveEditboxes && THEME_CONTROL_TYPE_EDITBOX == pControl->type && pControl->sczName && *pControl->sczName) | 5561 | fSaveEditboxes && THEME_CONTROL_TYPE_EDITBOX == pControl->type && pControl->sczName && *pControl->sczName) |
5662 | { | 5562 | { |
5663 | hr = ThemeGetTextControl(pTheme, pControl->wId, &sczText); | 5563 | hr = ThemeGetTextControl(pControl, &sczText); |
5664 | ThmExitOnFailure(hr, "Failed to get the text for control: %ls", pControl->sczName); | 5564 | ThmExitOnFailure(hr, "Failed to get the text for control: %ls", pControl->sczName); |
5665 | 5565 | ||
5666 | hr = pTheme->pfnSetStringVariable(pControl->sczName, sczText, FALSE, pTheme->pvVariableContext); | 5566 | hr = pTheme->pfnSetStringVariable(pControl->sczName, sczText, FALSE, pTheme->pvVariableContext); |
@@ -5675,7 +5575,7 @@ static HRESULT ShowControl( | |||
5675 | 5575 | ||
5676 | if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type) | 5576 | if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type) |
5677 | { | 5577 | { |
5678 | StopBillboard(pTheme, pControl->wId); | 5578 | StopBillboard(pTheme, pControl); |
5679 | } | 5579 | } |
5680 | 5580 | ||
5681 | ExitFunction(); | 5581 | ExitFunction(); |
@@ -5767,7 +5667,7 @@ static HRESULT ShowControl( | |||
5767 | ReleaseNullStr(sczText); | 5667 | ReleaseNullStr(sczText); |
5768 | } | 5668 | } |
5769 | 5669 | ||
5770 | ThemeSetTextControl(pTheme, pControl->wId, sczText); | 5670 | ThemeSetTextControl(pControl, sczText); |
5771 | 5671 | ||
5772 | if (wzNote && *wzNote) | 5672 | if (wzNote && *wzNote) |
5773 | { | 5673 | { |
@@ -5811,7 +5711,7 @@ static HRESULT ShowControl( | |||
5811 | ++iPageControl; | 5711 | ++iPageControl; |
5812 | } | 5712 | } |
5813 | 5713 | ||
5814 | ThemeSendControlMessage(pTheme, pControl->wId, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0); | 5714 | ::SendMessageW(pControl->hWnd, BM_SETCHECK, SUCCEEDED(hr) && llValue ? BST_CHECKED : BST_UNCHECKED, 0); |
5815 | } | 5715 | } |
5816 | 5716 | ||
5817 | // If this is an editbox control, | 5717 | // If this is an editbox control, |
@@ -5838,7 +5738,7 @@ static HRESULT ShowControl( | |||
5838 | ++iPageControl; | 5738 | ++iPageControl; |
5839 | } | 5739 | } |
5840 | 5740 | ||
5841 | ThemeSetTextControl(pTheme, pControl->wId, sczText); | 5741 | ThemeSetTextControl(pControl, sczText); |
5842 | } | 5742 | } |
5843 | } | 5743 | } |
5844 | 5744 | ||
@@ -5901,11 +5801,11 @@ static HRESULT ShowControl( | |||
5901 | { | 5801 | { |
5902 | if (fEnabled) | 5802 | if (fEnabled) |
5903 | { | 5803 | { |
5904 | StartBillboard(pTheme, pControl->wId); | 5804 | StartBillboard(pTheme, pControl); |
5905 | } | 5805 | } |
5906 | else | 5806 | else |
5907 | { | 5807 | { |
5908 | StopBillboard(pTheme, pControl->wId); | 5808 | StopBillboard(pTheme, pControl); |
5909 | } | 5809 | } |
5910 | } | 5810 | } |
5911 | 5811 | ||
@@ -5944,7 +5844,7 @@ static HRESULT ShowControls( | |||
5944 | // Only look at non-page controls and the specified page's controls. | 5844 | // Only look at non-page controls and the specified page's controls. |
5945 | if (!pControl->wPageId || pControl->wPageId == dwPageId) | 5845 | if (!pControl->wPageId || pControl->wPageId == dwPageId) |
5946 | { | 5846 | { |
5947 | hr = ShowControl(pTheme, pControl, nCmdShow, fSaveEditboxes, reason, dwPageId, &hwndFocus); | 5847 | hr = ShowControl(pControl, nCmdShow, fSaveEditboxes, reason, dwPageId, &hwndFocus); |
5948 | ThmExitOnFailure(hr, "Failed to show control '%ls' at index %d.", pControl->sczName, i); | 5848 | ThmExitOnFailure(hr, "Failed to show control '%ls' at index %d.", pControl->sczName, i); |
5949 | } | 5849 | } |
5950 | } | 5850 | } |
@@ -6509,7 +6409,7 @@ static HRESULT LoadControls( | |||
6509 | HRESULT hrFormat = pTheme->pfnFormatString(pControl->sczText, &sczText, pTheme->pvVariableContext); | 6409 | HRESULT hrFormat = pTheme->pfnFormatString(pControl->sczText, &sczText, pTheme->pvVariableContext); |
6510 | if (SUCCEEDED(hrFormat)) | 6410 | if (SUCCEEDED(hrFormat)) |
6511 | { | 6411 | { |
6512 | ThemeSetTextControl(pTheme, pControl->wId, sczText); | 6412 | ThemeSetTextControl(pControl, sczText); |
6513 | } | 6413 | } |
6514 | } | 6414 | } |
6515 | 6415 | ||