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