Add the same bitmap to the settings page too.
[reactos.git] / reactos / dll / cpl / desk / background.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Display Control Panel
5 * FILE: lib/cpl/desk/background.c
6 * PURPOSE: Background property page
7 *
8 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
9 */
10
11 #include "desk.h"
12
13 #define MAX_BACKGROUNDS 100
14
15 #define PLACEMENT_CENTER 0
16 #define PLACEMENT_STRETCH 1
17 #define PLACEMENT_TILE 2
18
19 typedef struct
20 {
21 BOOL bWallpaper; /* Is this background a wallpaper */
22
23 TCHAR szFilename[MAX_PATH];
24 TCHAR szDisplayName[256];
25
26 } BackgroundItem;
27
28 BackgroundItem g_backgroundItems[MAX_BACKGROUNDS];
29
30 DIBitmap *g_pWallpaperBitmap = NULL;
31
32 int g_placementSelection = 0;
33 int g_backgroundSelection = 0;
34
35 int g_listViewItemCount = 0;
36
37 HWND g_hBackgroundPage = NULL;
38 HWND g_hBackgroundList = NULL;
39 HWND g_hBackgroundPreview = NULL;
40
41 HWND g_hPlacementCombo = NULL;
42 HWND g_hColorButton = NULL;
43
44 HIMAGELIST g_hShellImageList = NULL;
45
46 static HBITMAP hBitmap = NULL;
47 static int cxSource, cySource;
48
49 /* Add the images in the C:\ReactOS directory and the current wallpaper if any */
50 void AddListViewItems()
51 {
52 WIN32_FIND_DATA fd;
53 HANDLE hFind;
54 TCHAR szSearchPath[MAX_PATH];
55 TCHAR szFileTypes[MAX_PATH];
56 LV_ITEM listItem;
57 LV_COLUMN dummy;
58 RECT clientRect;
59 HKEY regKey;
60 SHFILEINFO sfi;
61 HIMAGELIST himl;
62 TCHAR wallpaperFilename[MAX_PATH];
63 DWORD bufferSize = sizeof(wallpaperFilename);
64 DWORD varType = REG_SZ;
65 LONG result;
66 UINT i = 0;
67 BackgroundItem *backgroundItem = NULL;
68 TCHAR separators[] = TEXT(";");
69 TCHAR *token;
70
71 GetClientRect(g_hBackgroundList, &clientRect);
72
73 ZeroMemory(&dummy, sizeof(LV_COLUMN));
74 dummy.mask = LVCF_SUBITEM | LVCF_WIDTH;
75 dummy.iSubItem = 0;
76 dummy.cx = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL);
77
78 (void)ListView_InsertColumn(g_hBackgroundList, 0, &dummy);
79
80 /* Add the "None" item */
81
82 backgroundItem = &g_backgroundItems[g_listViewItemCount];
83
84 backgroundItem->bWallpaper = FALSE;
85
86 LoadString(hApplet,
87 IDS_NONE,
88 backgroundItem->szDisplayName,
89 sizeof(backgroundItem->szDisplayName) / sizeof(TCHAR));
90
91 ZeroMemory(&listItem, sizeof(LV_ITEM));
92 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
93 listItem.state = LVIS_SELECTED;
94 listItem.pszText = backgroundItem->szDisplayName;
95 listItem.iImage = -1;
96 listItem.iItem = g_listViewItemCount;
97 listItem.lParam = g_listViewItemCount;
98
99 (void)ListView_InsertItem(g_hBackgroundList, &listItem);
100 ListView_SetItemState(g_hBackgroundList, g_listViewItemCount, LVIS_SELECTED, LVIS_SELECTED);
101
102 g_listViewItemCount++;
103
104 /* Add current wallpaper if any */
105
106 RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, &regKey);
107
108 result = RegQueryValueEx(regKey, TEXT("Wallpaper"), 0, &varType, (LPBYTE)wallpaperFilename, &bufferSize);
109
110 if((result == ERROR_SUCCESS) && (_tcslen(wallpaperFilename) > 0))
111 {
112 himl = (HIMAGELIST)SHGetFileInfo(wallpaperFilename,
113 0,
114 &sfi,
115 sizeof(sfi),
116 SHGFI_SYSICONINDEX | SHGFI_SMALLICON |
117 SHGFI_DISPLAYNAME);
118
119 if(himl != NULL)
120 {
121 if(i++ == 0)
122 {
123 g_hShellImageList = himl;
124 (void)ListView_SetImageList(g_hBackgroundList, himl, LVSIL_SMALL);
125 }
126
127 backgroundItem = &g_backgroundItems[g_listViewItemCount];
128
129 backgroundItem->bWallpaper = TRUE;
130
131 _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName);
132 _tcscpy(backgroundItem->szFilename, wallpaperFilename);
133
134 ZeroMemory(&listItem, sizeof(LV_ITEM));
135 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
136 listItem.state = LVIS_SELECTED;
137 listItem.pszText = backgroundItem->szDisplayName;
138 listItem.iImage = sfi.iIcon;
139 listItem.iItem = g_listViewItemCount;
140 listItem.lParam = g_listViewItemCount;
141
142 (void)ListView_InsertItem(g_hBackgroundList, &listItem);
143 ListView_SetItemState(g_hBackgroundList, g_listViewItemCount, LVIS_SELECTED, LVIS_SELECTED);
144
145 g_listViewItemCount++;
146 }
147 }
148
149 RegCloseKey(regKey);
150
151 /* Add all the images in the C:\ReactOS directory. */
152
153 LoadString(hApplet, IDS_SUPPORTED_EXT, szFileTypes, sizeof(szFileTypes) / sizeof(TCHAR));
154
155
156 token = _tcstok ( szFileTypes, separators );
157 while ( token != NULL )
158 {
159 GetWindowsDirectory(szSearchPath, MAX_PATH);
160 _tcscat(szSearchPath, TEXT("\\"));
161 _tcscat(szSearchPath, token);
162
163 hFind = FindFirstFile(szSearchPath, &fd);
164 while(hFind != INVALID_HANDLE_VALUE)
165 {
166 /* Don't add any hidden bitmaps */
167 if((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0)
168 {
169 TCHAR filename[MAX_PATH];
170
171 GetWindowsDirectory(filename, MAX_PATH);
172
173 _tcscat(filename, TEXT("\\"));
174 _tcscat(filename, fd.cFileName);
175
176 himl = (HIMAGELIST)SHGetFileInfo(filename,
177 0,
178 &sfi,
179 sizeof(sfi),
180 SHGFI_SYSICONINDEX | SHGFI_SMALLICON |
181 SHGFI_DISPLAYNAME);
182
183 if(himl == NULL)
184 {
185 break;
186 }
187
188 if(i++ == 0)
189 {
190 g_hShellImageList = himl;
191 (void)ListView_SetImageList(g_hBackgroundList, himl, LVSIL_SMALL);
192 }
193
194 backgroundItem = &g_backgroundItems[g_listViewItemCount];
195
196 backgroundItem->bWallpaper = TRUE;
197
198 _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName);
199 _tcscpy(backgroundItem->szFilename, filename);
200
201 ZeroMemory(&listItem, sizeof(LV_ITEM));
202 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
203 listItem.pszText = backgroundItem->szDisplayName;
204 listItem.state = 0;
205 listItem.iImage = sfi.iIcon;
206 listItem.iItem = g_listViewItemCount;
207 listItem.lParam = g_listViewItemCount;
208
209 (void)ListView_InsertItem(g_hBackgroundList, &listItem);
210
211 g_listViewItemCount++;
212 }
213
214 if(!FindNextFile(hFind, &fd))
215 hFind = INVALID_HANDLE_VALUE;
216 }
217
218 token = _tcstok ( NULL, separators );
219 }
220
221
222 }
223
224 void InitBackgroundDialog()
225 {
226 TCHAR szString[256];
227 HKEY regKey;
228 TCHAR szBuffer[2];
229 DWORD bufferSize = sizeof(szBuffer);
230 DWORD varType = REG_SZ;
231 LONG result;
232 BITMAP bitmap;
233
234 g_hBackgroundList = GetDlgItem(g_hBackgroundPage, IDC_BACKGROUND_LIST);
235 g_hBackgroundPreview = GetDlgItem(g_hBackgroundPage, IDC_BACKGROUND_PREVIEW);
236 g_hPlacementCombo = GetDlgItem(g_hBackgroundPage, IDC_PLACEMENT_COMBO);
237 g_hColorButton = GetDlgItem(g_hBackgroundPage, IDC_COLOR_BUTTON);
238
239 AddListViewItems();
240
241 LoadString(hApplet, IDS_CENTER, szString, sizeof(szString) / sizeof(TCHAR));
242 SendMessage(g_hPlacementCombo, CB_INSERTSTRING, PLACEMENT_CENTER, (LPARAM)szString);
243
244 LoadString(hApplet, IDS_STRETCH, szString, sizeof(szString) / sizeof(TCHAR));
245 SendMessage(g_hPlacementCombo, CB_INSERTSTRING, PLACEMENT_STRETCH, (LPARAM)szString);
246
247 LoadString(hApplet, IDS_TILE, szString, sizeof(szString) / sizeof(TCHAR));
248 SendMessage(g_hPlacementCombo, CB_INSERTSTRING, PLACEMENT_TILE, (LPARAM)szString);
249
250 /* Load the default settings from the registry */
251 RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, &regKey);
252
253 result = RegQueryValueEx(regKey, TEXT("WallpaperStyle"), 0, &varType, (LPBYTE)szBuffer, &bufferSize);
254
255 if(result == ERROR_SUCCESS)
256 {
257 if(_ttoi(szBuffer) == 0)
258 {
259 SendMessage(g_hPlacementCombo, CB_SETCURSEL, PLACEMENT_CENTER, 0);
260 g_placementSelection = PLACEMENT_CENTER;
261 }
262
263 if(_ttoi(szBuffer) == 2)
264 {
265 SendMessage(g_hPlacementCombo, CB_SETCURSEL, PLACEMENT_STRETCH, 0);
266 g_placementSelection = PLACEMENT_STRETCH;
267 }
268 }
269 else
270 {
271 SendMessage(g_hPlacementCombo, CB_SETCURSEL, PLACEMENT_CENTER, 0);
272 g_placementSelection = PLACEMENT_CENTER;
273 }
274
275 result = RegQueryValueEx(regKey, TEXT("TileWallpaper"), 0, &varType, (LPBYTE)szBuffer, &bufferSize);
276
277 if(result == ERROR_SUCCESS)
278 {
279 if(_ttoi(szBuffer) == 1)
280 {
281 SendMessage(g_hPlacementCombo, CB_SETCURSEL, PLACEMENT_TILE, 0);
282 g_placementSelection = PLACEMENT_TILE;
283 }
284 }
285
286 RegCloseKey(regKey);
287
288 hBitmap = LoadImage(hApplet, MAKEINTRESOURCE(IDC_MONITOR), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);
289 if (hBitmap != NULL)
290 {
291 GetObject(hBitmap, sizeof(BITMAP), &bitmap);
292
293 cxSource = bitmap.bmWidth;
294 cySource = bitmap.bmHeight;
295 }
296 }
297
298 void OnColorButton()
299 {
300 MessageBox(NULL, TEXT("That button doesn't do anything yet"), TEXT("Whoops"), MB_OK);
301 }
302
303 BOOL CheckListBoxFilename(HWND list, TCHAR *filename)
304 {
305 return FALSE;
306 }
307
308 void OnBrowseButton()
309 {
310 OPENFILENAME ofn;
311 TCHAR filename[MAX_PATH];
312 TCHAR fileTitle[256];
313 TCHAR filter[MAX_PATH];
314 BackgroundItem *backgroundItem = NULL;
315 SHFILEINFO sfi;
316 LV_ITEM listItem;
317
318 ZeroMemory(&ofn, sizeof(OPENFILENAME));
319
320 ofn.lStructSize = sizeof(OPENFILENAME);
321 ofn.hwndOwner = g_hBackgroundPage;
322 ofn.lpstrFile = filename;
323
324 LoadString(hApplet, IDS_BACKGROUND_COMDLG_FILTER, filter, sizeof(filter) / sizeof(TCHAR));
325
326 /* Set lpstrFile[0] to '\0' so that GetOpenFileName does not
327 * use the contents of szFile to initialize itself */
328 ofn.lpstrFile[0] = TEXT('\0');
329 ofn.nMaxFile = MAX_PATH;
330 ofn.lpstrFilter = filter;
331 ofn.nFilterIndex = 0;
332 ofn.lpstrFileTitle = fileTitle;
333 ofn.nMaxFileTitle = 256;
334 ofn.lpstrInitialDir = NULL;
335 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
336
337 if(GetOpenFileName(&ofn) == TRUE)
338 {
339 /* Check if there is already a entry that holds this filename */
340 if(CheckListBoxFilename(g_hBackgroundList, filename) == TRUE)
341 return;
342
343 if(g_listViewItemCount > (MAX_BACKGROUNDS - 1))
344 return;
345
346 SHGetFileInfo(filename,
347 0,
348 &sfi,
349 sizeof(sfi),
350 SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_DISPLAYNAME);
351
352 backgroundItem = &g_backgroundItems[g_listViewItemCount];
353
354 backgroundItem->bWallpaper = TRUE;
355
356 _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName);
357 _tcscpy(backgroundItem->szFilename, filename);
358
359 ZeroMemory(&listItem, sizeof(LV_ITEM));
360 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
361 listItem.state = 0;
362 listItem.pszText = backgroundItem->szDisplayName;
363 listItem.iImage = sfi.iIcon;
364 listItem.iItem = g_listViewItemCount;
365 listItem.lParam = g_listViewItemCount;
366
367 (void)ListView_InsertItem(g_hBackgroundList, &listItem);
368
369 g_listViewItemCount++;
370 }
371 }
372
373 void ListViewItemChanged(int itemIndex)
374 {
375 BackgroundItem *backgroundItem = NULL;
376
377 g_backgroundSelection = itemIndex;
378 backgroundItem = &g_backgroundItems[g_backgroundSelection];
379
380 if(g_pWallpaperBitmap != NULL)
381 {
382 DibFreeImage(g_pWallpaperBitmap);
383 g_pWallpaperBitmap = NULL;
384 }
385
386 if(backgroundItem->bWallpaper == TRUE)
387 {
388 g_pWallpaperBitmap = DibLoadImage(backgroundItem->szFilename);
389
390 if(g_pWallpaperBitmap == NULL)
391 {
392 return;
393 }
394 }
395
396 InvalidateRect(g_hBackgroundPreview, NULL, TRUE);
397
398 EnableWindow(g_hColorButton, (backgroundItem->bWallpaper == FALSE ? TRUE : FALSE));
399 EnableWindow(g_hPlacementCombo, backgroundItem->bWallpaper);
400
401 PropSheet_Changed(GetParent(g_hBackgroundPage), g_hBackgroundPage);
402 }
403
404 void DrawBackgroundPreview(LPDRAWITEMSTRUCT draw)
405 {
406 float scaleX;
407 float scaleY;
408 int scaledWidth;
409 int scaledHeight;
410 int posX;
411 int posY;
412
413 if(g_backgroundItems[g_backgroundSelection].bWallpaper == FALSE)
414 {
415 FillRect(draw->hDC, &draw->rcItem, GetSysColorBrush(COLOR_BACKGROUND));
416 return;
417 }
418
419 if(g_pWallpaperBitmap == NULL)
420 return;
421
422 scaleX = ((float)GetSystemMetrics(SM_CXSCREEN) - 1) / (float)draw->rcItem.right;
423 scaleY = ((float)GetSystemMetrics(SM_CYSCREEN) - 1) / (float)draw->rcItem.bottom;
424
425 scaledWidth = g_pWallpaperBitmap->width / scaleX;
426 scaledHeight = g_pWallpaperBitmap->height / scaleY;
427
428 posX = (draw->rcItem.right / 2) - (scaledWidth / 2);
429 posY = (draw->rcItem.bottom / 2) - (scaledHeight / 2);
430
431 FillRect(draw->hDC, &draw->rcItem, GetSysColorBrush(COLOR_BACKGROUND));
432
433 SetStretchBltMode(draw->hDC, COLORONCOLOR);
434
435 if(g_placementSelection == PLACEMENT_CENTER)
436 {
437 StretchDIBits(draw->hDC,
438 posX,
439 posY,
440 scaledWidth,
441 scaledHeight,
442 0,
443 0,
444 g_pWallpaperBitmap->width,
445 g_pWallpaperBitmap->height,
446 g_pWallpaperBitmap->bits,
447 g_pWallpaperBitmap->info,
448 DIB_RGB_COLORS,
449 SRCCOPY);
450 }
451
452 if(g_placementSelection == PLACEMENT_STRETCH)
453 {
454 StretchDIBits(draw->hDC,
455 0,
456 0,
457 draw->rcItem.right,
458 draw->rcItem.bottom,
459 0,
460 0,
461 g_pWallpaperBitmap->width,
462 g_pWallpaperBitmap->height,
463 g_pWallpaperBitmap->bits,
464 g_pWallpaperBitmap->info,
465 DIB_RGB_COLORS,
466 SRCCOPY);
467 }
468
469 if(g_placementSelection == PLACEMENT_TILE)
470 {
471 int x;
472 int y;
473
474 for(y = 0; y < draw->rcItem.bottom; y += scaledHeight)
475 {
476 for(x = 0; x < draw->rcItem.right; x += scaledWidth)
477 {
478 StretchDIBits(draw->hDC,
479 x,
480 y,
481 scaledWidth,
482 scaledHeight,
483 0,
484 0,
485 g_pWallpaperBitmap->width,
486 g_pWallpaperBitmap->height,
487 g_pWallpaperBitmap->bits,
488 g_pWallpaperBitmap->info,
489 DIB_RGB_COLORS,
490 SRCCOPY);
491 }
492 }
493 }
494 }
495
496 void SetWallpaper()
497 {
498 HKEY regKey;
499
500 RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, &regKey);
501
502 if(g_placementSelection == PLACEMENT_TILE)
503 {
504 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("1"), sizeof(TCHAR) * 2);
505 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2);
506 }
507
508 if(g_placementSelection == PLACEMENT_CENTER)
509 {
510 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2);
511 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2);
512 }
513
514 if(g_placementSelection == PLACEMENT_STRETCH)
515 {
516 RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2);
517 RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("2"), sizeof(TCHAR) * 2);
518 }
519
520 RegCloseKey(regKey);
521
522 if(g_backgroundItems[g_backgroundSelection].bWallpaper == TRUE)
523 {
524 SystemParametersInfo(SPI_SETDESKWALLPAPER,
525 0,
526 g_backgroundItems[g_backgroundSelection].szFilename,
527 SPIF_UPDATEINIFILE);
528 }
529 else
530 {
531 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, TEXT(""), SPIF_UPDATEINIFILE);
532 }
533 }
534
535 INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg,
536 UINT uMsg,
537 WPARAM wParam,
538 LPARAM lParam)
539 {
540 g_hBackgroundPage = hwndDlg;
541
542 switch(uMsg)
543 {
544 case WM_INITDIALOG:
545 {
546 InitBackgroundDialog();
547 } break;
548
549 case WM_COMMAND:
550 {
551 DWORD controlId = LOWORD(wParam);
552 DWORD command = HIWORD(wParam);
553
554 switch(controlId)
555 {
556 case IDC_COLOR_BUTTON:
557 {
558 if(command == BN_CLICKED)
559 OnColorButton();
560
561 } break;
562
563 case IDC_BROWSE_BUTTON:
564 {
565 if(command == BN_CLICKED)
566 OnBrowseButton();
567
568 } break;
569
570 case IDC_PLACEMENT_COMBO:
571 {
572 if(command == CBN_SELCHANGE)
573 {
574 g_placementSelection = SendMessage(g_hPlacementCombo, CB_GETCURSEL, 0, 0);
575
576 InvalidateRect(g_hBackgroundPreview, NULL, TRUE);
577
578 PropSheet_Changed(GetParent(g_hBackgroundPage), g_hBackgroundPage);
579 }
580
581 } break;
582 }
583 } break;
584
585 case WM_PAINT:
586 {
587 PAINTSTRUCT ps;
588 HDC hdc, hdcMem;
589
590 hdc = BeginPaint(hwndDlg, &ps);
591
592 hdcMem = CreateCompatibleDC(hdc);
593 SelectObject(hdcMem, hBitmap);
594
595 BitBlt(hdc, 98, 0, cxSource, cySource, hdcMem, 0, 0, SRCCOPY);
596
597 DeleteDC(hdcMem);
598 EndPaint(hwndDlg, &ps);
599
600 } break;
601
602 case WM_DRAWITEM:
603 {
604 LPDRAWITEMSTRUCT drawItem;
605 drawItem = (LPDRAWITEMSTRUCT)lParam;
606
607 if(drawItem->CtlID == IDC_BACKGROUND_PREVIEW)
608 {
609 DrawBackgroundPreview(drawItem);
610 }
611
612 } break;
613
614 case WM_NOTIFY:
615 {
616 LPNMHDR lpnm = (LPNMHDR)lParam;
617
618 switch(lpnm->code)
619 {
620 case PSN_APPLY:
621 {
622 SetWallpaper();
623
624 return TRUE;
625 } break;
626
627 case LVN_ITEMCHANGED:
628 {
629 LPNMLISTVIEW nm = (LPNMLISTVIEW)lParam;
630
631 if((nm->uNewState & LVIS_SELECTED) == 0)
632 return FALSE;
633
634 ListViewItemChanged(nm->iItem);
635
636 } break;
637
638 default:
639 break;
640 }
641
642 } break;
643
644 case WM_DESTROY:
645 {
646 if(g_pWallpaperBitmap != NULL)
647 DibFreeImage(g_pWallpaperBitmap);
648
649 DeleteObject(hBitmap);
650
651 } break;
652 }
653
654 return FALSE;
655 }
656