[KSPROXY]
[reactos.git] / reactos / dll / cpl / desk / settings.c
index 44048d2..1ede0e7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS Display Control Panel
- * FILE:            lib/cpl/desk/settings.c
+ * FILE:            dll/cpl/desk/settings.c
  * PURPOSE:         Settings property page
  *
  * PROGRAMMERS:     Trevor McCort (lycan359@gmail.com)
@@ -9,71 +9,45 @@
  */
 
 #include "desk.h"
+#include "monslctl.h"
 
-/* As slider control can't contain user data, we have to keep an
- * array of RESOLUTION_INFO to have our own associated data.
- */
-typedef struct _RESOLUTION_INFO
+typedef struct _GLOBAL_DATA
 {
-       DWORD dmPelsWidth;
-       DWORD dmPelsHeight;
-} RESOLUTION_INFO, *PRESOLUTION_INFO;
+       PDISPLAY_DEVICE_ENTRY DisplayDeviceList;
+       PDISPLAY_DEVICE_ENTRY CurrentDisplayDevice;
+       HBITMAP hSpectrumBitmaps[NUM_SPECTRUM_BITMAPS];
+       int cxSource[NUM_SPECTRUM_BITMAPS];
+       int cySource[NUM_SPECTRUM_BITMAPS];
+} GLOBAL_DATA, *PGLOBAL_DATA;
 
-typedef struct _SETTINGS_ENTRY
-{
-       struct _SETTINGS_ENTRY *Blink;
-       struct _SETTINGS_ENTRY *Flink;
-       DWORD dmBitsPerPel;
-       DWORD dmPelsWidth;
-       DWORD dmPelsHeight;
-} SETTINGS_ENTRY, *PSETTINGS_ENTRY;
-
-typedef struct _DISPLAY_DEVICE_ENTRY
-{
-       struct _DISPLAY_DEVICE_ENTRY *Flink;
-       LPTSTR DeviceDescription;
-       LPTSTR DeviceName;
-       PSETTINGS_ENTRY Settings; /* sorted by increasing dmPelsHeight, BPP */
-       DWORD SettingsCount;
-       PRESOLUTION_INFO Resolutions;
-       DWORD ResolutionsCount;
-       PSETTINGS_ENTRY CurrentSettings; /* Points into Settings list */
-       SETTINGS_ENTRY InitialSettings;
-} DISPLAY_DEVICE_ENTRY, *PDISPLAY_DEVICE_ENTRY;
-
-static PDISPLAY_DEVICE_ENTRY DisplayDeviceList = NULL;
-static PDISPLAY_DEVICE_ENTRY CurrentDisplayDevice = NULL;
-
-HBITMAP hBitmap = NULL;
-int cxSource, cySource;
 
 static VOID
-UpdateDisplay(IN HWND hwndDlg)
+UpdateDisplay(IN HWND hwndDlg, PGLOBAL_DATA pGlobalData, IN BOOL bUpdateThumb)
 {
        TCHAR Buffer[64];
        TCHAR Pixel[64];
        DWORD index;
 
        LoadString(hApplet, IDS_PIXEL, Pixel, sizeof(Pixel) / sizeof(TCHAR));
-       _stprintf(Buffer, Pixel, CurrentDisplayDevice->CurrentSettings->dmPelsWidth, CurrentDisplayDevice->CurrentSettings->dmPelsHeight, Pixel);
+       _stprintf(Buffer, Pixel, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight, Pixel);
        SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT, WM_SETTEXT, 0, (LPARAM)Buffer);
 
-       for (index = 0; index < CurrentDisplayDevice->ResolutionsCount; index++)
+       for (index = 0; index < pGlobalData->CurrentDisplayDevice->ResolutionsCount; index++)
        {
-
-               if (CurrentDisplayDevice->Resolutions[index].dmPelsWidth == CurrentDisplayDevice->CurrentSettings->dmPelsWidth &&
-                   CurrentDisplayDevice->Resolutions[index].dmPelsHeight == CurrentDisplayDevice->CurrentSettings->dmPelsHeight)
+               if (pGlobalData->CurrentDisplayDevice->Resolutions[index].dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth &&
+                   pGlobalData->CurrentDisplayDevice->Resolutions[index].dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight)
                {
-                       SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETPOS, TRUE, index);
+                       if (bUpdateThumb)
+                               SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETPOS, TRUE, index);
                        break;
                }
        }
-       if (LoadString(hApplet, (2900 + CurrentDisplayDevice->CurrentSettings->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
+       if (LoadString(hApplet, (2900 + pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
                SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)Buffer);
 }
 
 static PSETTINGS_ENTRY
-GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTINGS_ENTRY* CurrentSettings)
+GetPossibleSettings(IN LPCTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTINGS_ENTRY* CurrentSettings)
 {
        DEVMODE devmode;
        DWORD NbSettings = 0;
@@ -83,6 +57,7 @@ GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTIN
        HDC hDC;
        PSETTINGS_ENTRY Current;
        DWORD bpp, xres, yres, checkbpp;
+       DWORD curDispFreq;
 
        /* Get current settings */
        *CurrentSettings = NULL;
@@ -96,10 +71,25 @@ GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTIN
        /* List all settings */
        devmode.dmSize = (WORD)sizeof(DEVMODE);
        devmode.dmDriverExtra = 0;
+
+       if (!EnumDisplaySettingsEx(DeviceName, ENUM_CURRENT_SETTINGS, &devmode, dwFlags))
+               return NULL;
+
+       curDispFreq = devmode.dmDisplayFrequency;
+
        while (EnumDisplaySettingsEx(DeviceName, iMode, &devmode, dwFlags))
        {
-               if (devmode.dmBitsPerPel==8 || devmode.dmBitsPerPel==16 || devmode.dmBitsPerPel==24 || devmode.dmBitsPerPel==32) checkbpp=1;
-               else checkbpp=0;
+               if ((devmode.dmBitsPerPel == 4 ||
+                    devmode.dmBitsPerPel == 8 ||
+                    devmode.dmBitsPerPel == 16 ||
+                    devmode.dmBitsPerPel == 24 ||
+                    devmode.dmBitsPerPel == 32) &&
+                    devmode.dmDisplayFrequency == curDispFreq)
+               {
+                       checkbpp=1;
+               }
+               else
+                       checkbpp=0;
 
                if (devmode.dmPelsWidth < 640 ||
                        devmode.dmPelsHeight < 480 || checkbpp == 0)
@@ -117,12 +107,13 @@ GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTIN
                        Current->dmPelsWidth = devmode.dmPelsWidth;
                        Current->dmPelsHeight = devmode.dmPelsHeight;
                        Current->dmBitsPerPel = devmode.dmBitsPerPel;
+                       Current->dmDisplayFrequency = devmode.dmDisplayFrequency;
                        while (Next != NULL && (
-                              Next->dmPelsHeight < Current->dmPelsHeight ||
-                              (Next->dmPelsHeight == Current->dmPelsHeight && Next->dmBitsPerPel < Current->dmBitsPerPel) ||
+                              Next->dmPelsWidth < Current->dmPelsWidth ||
+                              (Next->dmPelsWidth == Current->dmPelsWidth && Next->dmPelsHeight < Current->dmPelsHeight) ||
                               (Next->dmPelsHeight == Current->dmPelsHeight &&
-                               Next->dmBitsPerPel == Current->dmBitsPerPel &&
-                               Next->dmPelsWidth < Current->dmPelsWidth)))
+                               Next->dmPelsWidth == Current->dmPelsWidth &&
+                               Next->dmBitsPerPel < Current->dmBitsPerPel )))
                        {
                                Previous = Next;
                                Next = Next->Flink;
@@ -149,22 +140,22 @@ GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTIN
 }
 
 static BOOL
-AddDisplayDevice(IN LPTSTR Description, IN LPTSTR DeviceName)
+AddDisplayDevice(IN PGLOBAL_DATA pGlobalData, IN const DISPLAY_DEVICE *DisplayDevice)
 {
        PDISPLAY_DEVICE_ENTRY newEntry = NULL;
        LPTSTR description = NULL;
        LPTSTR name = NULL;
-       DWORD descriptionSize;
-       DWORD nameSize;
+       LPTSTR key = NULL;
+       LPTSTR devid = NULL;
+       DWORD descriptionSize, nameSize, keySize, devidSize;
        PSETTINGS_ENTRY Current;
        DWORD ResolutionsCount = 1;
        DWORD i;
 
-       newEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(DISPLAY_DEVICE_ENTRY));
-       memset(newEntry, 0, sizeof(DISPLAY_DEVICE_ENTRY));
+       newEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISPLAY_DEVICE_ENTRY));
        if (!newEntry) goto ByeBye;
 
-       newEntry->Settings = GetPossibleSettings(DeviceName, &newEntry->SettingsCount, &newEntry->CurrentSettings);
+       newEntry->Settings = GetPossibleSettings(DisplayDevice->DeviceName, &newEntry->SettingsCount, &newEntry->CurrentSettings);
        if (!newEntry->Settings) goto ByeBye;
 
        newEntry->InitialSettings.dmPelsWidth = newEntry->CurrentSettings->dmPelsWidth;
@@ -173,36 +164,60 @@ AddDisplayDevice(IN LPTSTR Description, IN LPTSTR DeviceName)
 
        /* Count different resolutions */
        for (Current = newEntry->Settings; Current != NULL; Current = Current->Flink)
+       {
                if (Current->Flink != NULL &&
-                  ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) || (Current->dmPelsHeight != Current->Flink->dmPelsHeight)))
+                       ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) &&
+                       (Current->dmPelsHeight != Current->Flink->dmPelsHeight)))
+               {
                        ResolutionsCount++;
+               }
+       }
+
        newEntry->Resolutions = HeapAlloc(GetProcessHeap(), 0, ResolutionsCount * sizeof(RESOLUTION_INFO));
        if (!newEntry->Resolutions) goto ByeBye;
+
        newEntry->ResolutionsCount = ResolutionsCount;
+
        /* Fill resolutions infos */
        for (Current = newEntry->Settings, i = 0; Current != NULL; Current = Current->Flink)
-               if (Current->Flink == NULL || (Current->Flink != NULL &&
-                   ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) || (Current->dmPelsHeight != Current->Flink->dmPelsHeight))))
+       {
+               if (Current->Flink == NULL ||
+                       (Current->Flink != NULL &&
+                       ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) &&
+                       (Current->dmPelsHeight != Current->Flink->dmPelsHeight))))
                {
                        newEntry->Resolutions[i].dmPelsWidth = Current->dmPelsWidth;
                        newEntry->Resolutions[i].dmPelsHeight = Current->dmPelsHeight;
                        i++;
                }
-
-       descriptionSize = (_tcslen(Description) + 1) * sizeof(TCHAR);
+       }
+       descriptionSize = (_tcslen(DisplayDevice->DeviceString) + 1) * sizeof(TCHAR);
        description = HeapAlloc(GetProcessHeap(), 0, descriptionSize);
        if (!description) goto ByeBye;
 
-       nameSize = (_tcslen(DeviceName) + 1) * sizeof(TCHAR);
+       nameSize = (_tcslen(DisplayDevice->DeviceName) + 1) * sizeof(TCHAR);
        name = HeapAlloc(GetProcessHeap(), 0, nameSize);
        if (!name) goto ByeBye;
 
-       memcpy(description, Description, descriptionSize);
-       memcpy(name, DeviceName, nameSize);
+       keySize = (_tcslen(DisplayDevice->DeviceKey) + 1) * sizeof(TCHAR);
+       key = HeapAlloc(GetProcessHeap(), 0, keySize);
+       if (!key) goto ByeBye;
+
+       devidSize = (_tcslen(DisplayDevice->DeviceID) + 1) * sizeof(TCHAR);
+       devid = HeapAlloc(GetProcessHeap(), 0, devidSize);
+       if (!devid) goto ByeBye;
+
+       memcpy(description, DisplayDevice->DeviceString, descriptionSize);
+       memcpy(name, DisplayDevice->DeviceName, nameSize);
+       memcpy(key, DisplayDevice->DeviceKey, keySize);
+       memcpy(devid, DisplayDevice->DeviceID, devidSize);
        newEntry->DeviceDescription = description;
        newEntry->DeviceName = name;
-       newEntry->Flink = DisplayDeviceList;
-       DisplayDeviceList = newEntry;
+       newEntry->DeviceKey = key;
+       newEntry->DeviceID = devid;
+       newEntry->DeviceStateFlags = DisplayDevice->StateFlags;
+       newEntry->Flink = pGlobalData->DisplayDeviceList;
+       pGlobalData->DisplayDeviceList = newEntry;
        return TRUE;
 
 ByeBye:
@@ -226,16 +241,18 @@ ByeBye:
                HeapFree(GetProcessHeap(), 0, description);
        if (name != NULL)
                HeapFree(GetProcessHeap(), 0, name);
+       if (key != NULL)
+               HeapFree(GetProcessHeap(), 0, key);
        return FALSE;
 }
 
 static VOID
-OnDisplayDeviceChanged(IN HWND hwndDlg, IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)
+OnDisplayDeviceChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)
 {
        PSETTINGS_ENTRY Current;
        DWORD index;
 
-       CurrentDisplayDevice = pDeviceEntry; /* Update global variable */
+       pGlobalData->CurrentDisplayDevice = pDeviceEntry; /* Update global variable */
 
        /* Fill color depths combo box */
        SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_RESETCONTENT, 0, 0);
@@ -257,28 +274,38 @@ OnDisplayDeviceChanged(IN HWND hwndDlg, IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)
        SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_CLEARTICS, TRUE, 0);
        SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETRANGE, TRUE, MAKELONG(0, pDeviceEntry->ResolutionsCount - 1));
 
-       UpdateDisplay(hwndDlg);
+       UpdateDisplay(hwndDlg, pGlobalData, TRUE);
 }
 
 static VOID
 OnInitDialog(IN HWND hwndDlg)
 {
+       BITMAP bitmap;
        DWORD Result = 0;
        DWORD iDevNum = 0;
+       DWORD i;
        DISPLAY_DEVICE displayDevice;
-       BITMAP bitmap;
+       PGLOBAL_DATA pGlobalData;
+
+       pGlobalData = HeapAlloc(GetProcessHeap(), 0, sizeof(GLOBAL_DATA));
+       if (pGlobalData == NULL)
+               return;
+
+       SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
 
        /* Get video cards list */
+       pGlobalData->DisplayDeviceList = NULL;
        displayDevice.cb = (DWORD)sizeof(DISPLAY_DEVICE);
-       while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0))
+       while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0x1))
        {
                if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0)
                {
-                       if (AddDisplayDevice(displayDevice.DeviceString, displayDevice.DeviceName))
+                       if (AddDisplayDevice(pGlobalData, &displayDevice))
                                Result++;
                }
                iDevNum++;
        }
+
        if (Result == 0)
        {
                /* No adapter found */
@@ -286,31 +313,117 @@ OnInitDialog(IN HWND hwndDlg)
                EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION), FALSE);
                EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT), FALSE);
                EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_ADVANCED), FALSE);
+               ShowWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_SPECTRUM), SW_HIDE);
+
+               /* Do not initialize the color spectrum bitmaps */
+               memset(pGlobalData->hSpectrumBitmaps, 0, sizeof(pGlobalData->hSpectrumBitmaps));
+               return;
        }
        else if (Result == 1)
        {
+               MONSL_MONINFO monitors;
+
                /* Single video adapter */
-               SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)DisplayDeviceList->DeviceDescription);
-               OnDisplayDeviceChanged(hwndDlg, DisplayDeviceList);
+               SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
+               OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
+
+               monitors.Position.x = monitors.Position.y = 0;
+               monitors.Size.cx = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
+               monitors.Size.cy = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
+               monitors.Flags = 0;
+               SendDlgItemMessage(hwndDlg,
+                                  IDC_SETTINGS_MONSEL,
+                                  MSLM_SETMONITORSINFO,
+                                  1,
+                                  (LPARAM)&monitors);
        }
-       else
+       else /* FIXME: incomplete! */
        {
-               /* FIXME: multi video adapter */
-               /* FIXME: choose selected adapter being the primary one */
+               PMONSL_MONINFO pMonitors;
+               DWORD i;
+
+               SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
+               OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
+
+               pMonitors = (PMONSL_MONINFO)HeapAlloc(GetProcessHeap(), 0, sizeof(MONSL_MONINFO) * Result);
+               if (pMonitors)
+               {
+                       DWORD hack = 1280;
+                       for (i = 0; i < Result; i++)
+                       {
+                               pMonitors[i].Position.x = hack * i;
+                               pMonitors[i].Position.y = 0;
+                               pMonitors[i].Size.cx = pGlobalData->DisplayDeviceList->CurrentSettings->dmPelsWidth;
+                               pMonitors[i].Size.cy = pGlobalData->DisplayDeviceList->CurrentSettings->dmPelsHeight;
+                               pMonitors[i].Flags = 0;
+                       }
+
+                       SendDlgItemMessage(hwndDlg,
+                                          IDC_SETTINGS_MONSEL,
+                                          MSLM_SETMONITORSINFO,
+                                          Result,
+                                          (LPARAM)pMonitors);
+
+                       HeapFree(GetProcessHeap(), 0, pMonitors);
+               }
        }
 
-       hBitmap = LoadImage(hApplet, MAKEINTRESOURCE(IDC_MONITOR), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);
-       if (hBitmap != NULL)
+       /* Initialize the color spectrum bitmaps */
+       for(i = 0; i < NUM_SPECTRUM_BITMAPS; i++)
        {
-               GetObject(hBitmap, sizeof(BITMAP), &bitmap);
+               pGlobalData->hSpectrumBitmaps[i] = LoadImageW(hApplet, MAKEINTRESOURCEW(IDB_SPECTRUM_4 + i), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
 
-               cxSource = bitmap.bmWidth;
-               cySource = bitmap.bmHeight;
+               if (pGlobalData->hSpectrumBitmaps[i] != NULL)
+               {
+                       if (GetObjectW(pGlobalData->hSpectrumBitmaps[i], sizeof(BITMAP), &bitmap) != 0)
+                       {
+                               pGlobalData->cxSource[i] = bitmap.bmWidth;
+                               pGlobalData->cySource[i] = bitmap.bmHeight;
+                       }
+                       else
+                       {
+                               pGlobalData->cxSource[i] = 0;
+                               pGlobalData->cySource[i] = 0;
+                       }
+               }
        }
 }
 
+/* Get the ID for GLOBAL_DATA::hSpectrumBitmaps */
 static VOID
-OnBPPChanged(IN HWND hwndDlg)
+ShowColorSpectrum(IN HDC hDC, IN LPRECT client, IN DWORD BitsPerPel, IN PGLOBAL_DATA pGlobalData)
+{
+       HDC hdcMem;
+       INT iBitmap;
+
+       hdcMem = CreateCompatibleDC(hDC);
+
+       if (!hdcMem)
+               return;
+
+       switch(BitsPerPel)
+       {
+               case 4:  iBitmap = 0; break;
+               case 8:  iBitmap = 1; break;
+               default: iBitmap = 2;
+       }
+
+       if (SelectObject(hdcMem, pGlobalData->hSpectrumBitmaps[iBitmap]))
+       {
+               StretchBlt(hDC,
+                          client->left, client->top,
+                          client->right - client->left,
+                          client->bottom - client->top,
+                          hdcMem, 0, 0,
+                          pGlobalData->cxSource[iBitmap],
+                          pGlobalData->cySource[iBitmap], SRCCOPY);
+       }
+
+       DeleteDC(hdcMem);
+}
+
+static VOID
+OnBPPChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData)
 {
        /* if new BPP is not compatible with resolution:
         * 1) try to find the nearest smaller matching resolution
@@ -319,14 +432,21 @@ OnBPPChanged(IN HWND hwndDlg)
        PSETTINGS_ENTRY Current;
        DWORD dmNewBitsPerPel;
        DWORD index;
-       TCHAR Buffer[64];
+       HDC hSpectrumDC;
+       HWND hSpectrumControl;
+       RECT client;
 
-       SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, WM_GETTEXT, (WPARAM)(sizeof(Buffer) / sizeof(TCHAR)), (LPARAM)Buffer);
-       index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
+       index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETCURSEL, 0, 0);
        dmNewBitsPerPel = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETITEMDATA, index, 0);
 
+       /* Show a new spectrum bitmap */
+       hSpectrumControl = GetDlgItem(hwndDlg, IDC_SETTINGS_SPECTRUM);
+       hSpectrumDC = GetDC(hSpectrumControl);
+       GetClientRect(hSpectrumControl, &client);
+       ShowColorSpectrum(hSpectrumDC, &client, dmNewBitsPerPel, pGlobalData);
+
        /* find if new parameters are valid */
-       Current = CurrentDisplayDevice->CurrentSettings;
+       Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
        if (dmNewBitsPerPel == Current->dmBitsPerPel)
        {
                /* no change */
@@ -341,11 +461,11 @@ OnBPPChanged(IN HWND hwndDlg)
                while (Current != NULL)
                {
                        if (Current->dmBitsPerPel == dmNewBitsPerPel
-                        && Current->dmPelsHeight == CurrentDisplayDevice->CurrentSettings->dmPelsHeight
-                        && Current->dmPelsWidth == CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
+                        && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
+                        && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
                        {
-                               CurrentDisplayDevice->CurrentSettings = Current;
-                               UpdateDisplay(hwndDlg);
+                               pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
+                               UpdateDisplay(hwndDlg, pGlobalData, TRUE);
                                return;
                        }
                        Current = Current->Blink;
@@ -357,11 +477,11 @@ OnBPPChanged(IN HWND hwndDlg)
                while (Current != NULL)
                {
                        if (Current->dmBitsPerPel == dmNewBitsPerPel
-                        && Current->dmPelsHeight == CurrentDisplayDevice->CurrentSettings->dmPelsHeight
-                        && Current->dmPelsWidth == CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
+                        && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
+                        && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
                        {
-                               CurrentDisplayDevice->CurrentSettings = Current;
-                               UpdateDisplay(hwndDlg);
+                               pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
+                               UpdateDisplay(hwndDlg, pGlobalData, TRUE);
                                return;
                        }
                        Current = Current->Flink;
@@ -369,26 +489,26 @@ OnBPPChanged(IN HWND hwndDlg)
        }
 
        /* search smaller resolution compatible with current color depth */
-       Current = CurrentDisplayDevice->CurrentSettings->Blink;
+       Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
        while (Current != NULL)
        {
                if (Current->dmBitsPerPel == dmNewBitsPerPel)
                {
-                       CurrentDisplayDevice->CurrentSettings = Current;
-                       UpdateDisplay(hwndDlg);
+                       pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
+                       UpdateDisplay(hwndDlg, pGlobalData, TRUE);
                        return;
                }
                Current = Current->Blink;
        }
 
        /* search bigger resolution compatible with current color depth */
-       Current = CurrentDisplayDevice->CurrentSettings->Flink;
+       Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
        while (Current != NULL)
        {
                if (Current->dmBitsPerPel == dmNewBitsPerPel)
                {
-                       CurrentDisplayDevice->CurrentSettings = Current;
-                       UpdateDisplay(hwndDlg);
+                       pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
+                       UpdateDisplay(hwndDlg, pGlobalData, TRUE);
                        return;
                }
                Current = Current->Flink;
@@ -398,18 +518,19 @@ OnBPPChanged(IN HWND hwndDlg)
 }
 
 static VOID
-OnResolutionChanged(IN HWND hwndDlg, IN DWORD NewPosition)
+OnResolutionChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN DWORD NewPosition,
+                    IN BOOL bUpdateThumb)
 {
        /* if new resolution is not compatible with color depth:
         * 1) try to find the nearest bigger matching color depth
         * 2) otherwise, get the nearest smaller color depth
         */
        PSETTINGS_ENTRY Current;
-       DWORD dmNewPelsHeight = CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
-       DWORD dmNewPelsWidth = CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
+       DWORD dmNewPelsHeight = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
+       DWORD dmNewPelsWidth = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
 
        /* find if new parameters are valid */
-       Current = CurrentDisplayDevice->CurrentSettings;
+       Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
        if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
        {
                /* no change */
@@ -425,10 +546,10 @@ OnResolutionChanged(IN HWND hwndDlg, IN DWORD NewPosition)
                {
                        if (Current->dmPelsHeight == dmNewPelsHeight
                         && Current->dmPelsWidth == dmNewPelsWidth
-                        && Current->dmBitsPerPel == CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
+                        && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
                        {
-                               CurrentDisplayDevice->CurrentSettings = Current;
-                               UpdateDisplay(hwndDlg);
+                               pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
+                               UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
                                return;
                        }
                        Current = Current->Blink;
@@ -441,10 +562,10 @@ OnResolutionChanged(IN HWND hwndDlg, IN DWORD NewPosition)
                {
                        if (Current->dmPelsHeight == dmNewPelsHeight
                         && Current->dmPelsWidth == dmNewPelsWidth
-                        && Current->dmBitsPerPel == CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
+                        && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
                        {
-                               CurrentDisplayDevice->CurrentSettings = Current;
-                               UpdateDisplay(hwndDlg);
+                               pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
+                               UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
                                return;
                        }
                        Current = Current->Flink;
@@ -452,26 +573,26 @@ OnResolutionChanged(IN HWND hwndDlg, IN DWORD NewPosition)
        }
 
        /* search bigger color depth compatible with current resolution */
-       Current = CurrentDisplayDevice->CurrentSettings->Flink;
+       Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
        while (Current != NULL)
        {
                if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
                {
-                       CurrentDisplayDevice->CurrentSettings = Current;
-                       UpdateDisplay(hwndDlg);
+                       pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
+                       UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
                        return;
                }
                Current = Current->Flink;
        }
 
        /* search smaller color depth compatible with current resolution */
-       Current = CurrentDisplayDevice->CurrentSettings->Blink;
+       Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
        while (Current != NULL)
        {
                if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
                {
-                       CurrentDisplayDevice->CurrentSettings = Current;
-                       UpdateDisplay(hwndDlg);
+                       pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
+                       UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
                        return;
                }
                Current = Current->Blink;
@@ -480,30 +601,60 @@ OnResolutionChanged(IN HWND hwndDlg, IN DWORD NewPosition)
        /* we shouldn't go there */
 }
 
-static VOID
-OnAdvancedButton()
+/* Property sheet page callback */
+UINT CALLBACK
+SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
 {
-       MessageBox(NULL, TEXT("That button doesn't do anything yet"), TEXT("Whoops"), MB_OK);
+       UINT Ret = 0;
+
+       switch (uMsg)
+       {
+               case PSPCB_CREATE:
+                       Ret = RegisterMonitorSelectionControl(hApplet);
+                       break;
+
+               case PSPCB_RELEASE:
+                       UnregisterMonitorSelectionControl(hApplet);
+                       break;
+       }
+
+       return Ret;
 }
 
 /* Property page dialog callback */
 INT_PTR CALLBACK
 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
 {
+       PGLOBAL_DATA pGlobalData;
+       TCHAR Message[1024], Title[256];
+
+       pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
+
        switch(uMsg)
        {
                case WM_INITDIALOG:
+               {
                        OnInitDialog(hwndDlg);
                        break;
+               }
+               case WM_DRAWITEM:
+               {
+                       LPDRAWITEMSTRUCT lpDrawItem;
+                       lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
+
+                       if (lpDrawItem->CtlID == IDC_SETTINGS_SPECTRUM)
+                               ShowColorSpectrum(lpDrawItem->hDC, &lpDrawItem->rcItem, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel, pGlobalData);
+                       break;
+               }
                case WM_COMMAND:
                {
                        DWORD controlId = LOWORD(wParam);
                        DWORD command   = HIWORD(wParam);
 
                        if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
-                               OnAdvancedButton();
+                               DisplayAdvancedSettings(hwndDlg, pGlobalData->CurrentDisplayDevice);
                        else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
-                               OnBPPChanged(hwndDlg);
+                               OnBPPChanged(hwndDlg, pGlobalData);
                        break;
                }
                case WM_HSCROLL:
@@ -519,8 +670,13 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar
                                case TB_ENDTRACK:
                                {
                                        DWORD newPosition = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_GETPOS, 0, 0);
-                                       OnResolutionChanged(hwndDlg, newPosition);
+                                       OnResolutionChanged(hwndDlg, pGlobalData, newPosition, TRUE);
+                                       break;
                                }
+
+                               case TB_THUMBTRACK:
+                                       OnResolutionChanged(hwndDlg, pGlobalData, HIWORD(wParam), FALSE);
+                                       break;
                        }
                        break;
                }
@@ -529,9 +685,9 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar
                        LPNMHDR lpnm = (LPNMHDR)lParam;
                        if (lpnm->code == (UINT)PSN_APPLY)
                        {
-                               if (CurrentDisplayDevice->CurrentSettings->dmPelsWidth != CurrentDisplayDevice->InitialSettings.dmPelsWidth
-                                || CurrentDisplayDevice->CurrentSettings->dmPelsHeight != CurrentDisplayDevice->InitialSettings.dmPelsHeight
-                                || CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
+                               if (pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth
+                                || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight
+                                || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
                                {
                                        /* FIXME: Need to test changes */
                                        /* Apply new settings */
@@ -539,12 +695,13 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar
                                        DEVMODE devmode;
                                        RtlZeroMemory(&devmode, sizeof(DEVMODE));
                                        devmode.dmSize = (WORD)sizeof(DEVMODE);
-                                       devmode.dmPelsWidth = CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
-                                       devmode.dmPelsHeight = CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
-                                       devmode.dmBitsPerPel = CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
-                                       devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
+                                       devmode.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
+                                       devmode.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
+                                       devmode.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
+                                       devmode.dmDisplayFrequency = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency;
+                                       devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
                                        rc = ChangeDisplaySettingsEx(
-                                               CurrentDisplayDevice->DeviceName,
+                                               pGlobalData->CurrentDisplayDevice->DeviceName,
                                                &devmode,
                                                NULL,
                                                CDS_UPDATEREGISTRY,
@@ -552,18 +709,20 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar
                                        switch (rc)
                                        {
                                                case DISP_CHANGE_SUCCESSFUL:
-                                                       CurrentDisplayDevice->InitialSettings.dmPelsWidth = CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
-                                                       CurrentDisplayDevice->InitialSettings.dmPelsHeight = CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
-                                                       CurrentDisplayDevice->InitialSettings.dmBitsPerPel = CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
-                                                       break;
-                                               case DISP_CHANGE_FAILED:
-                                                       MessageBox(NULL, TEXT("Failed to apply new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
+                                                       pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
+                                                       pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
+                                                       pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
                                                        break;
                                                case DISP_CHANGE_RESTART:
-                                                       MessageBox(NULL, TEXT("You need to restart your computer to apply changes."), TEXT("Display settings"), MB_OK | MB_ICONINFORMATION);
+                                                       LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
+                                                       LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, sizeof(Message) / sizeof (TCHAR));
+                                                       MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION);
                                                        break;
+                                               case DISP_CHANGE_FAILED:
                                                default:
-                                                       MessageBox(NULL, TEXT("Unknown error when applying new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
+                                                       LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
+                                                       LoadString(hApplet, IDS_APPLY_FAILED, Message, sizeof(Message) / sizeof (TCHAR));
+                                                       MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP);
                                                        break;
                                        }
                                }
@@ -571,27 +730,111 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar
                        break;
                }
 
-               case WM_PAINT:
+               case WM_CONTEXTMENU:
                {
-                       PAINTSTRUCT ps;
-                       HDC hdc, hdcMem;
-
-                       hdc = BeginPaint(hwndDlg, &ps);
-
-                       hdcMem = CreateCompatibleDC(hdc);
-                       SelectObject(hdcMem, hBitmap);
-
-                       TransparentBlt(hdc, 98, 0, cxSource, cySource, hdcMem, 0, 0, cxSource, cySource, 0xFF80FF);
-
-                       DeleteDC(hdcMem);
-                       EndPaint(hwndDlg, &ps);
+                       HWND hwndMonSel;
+                       HMENU hPopup;
+                       UINT uiCmd;
+                       POINT pt, ptClient;
+                       INT Index;
+
+                       pt.x = (SHORT)LOWORD(lParam);
+                       pt.y = (SHORT)HIWORD(lParam);
+
+                       hwndMonSel = GetDlgItem(hwndDlg,
+                                               IDC_SETTINGS_MONSEL);
+                       if ((HWND)wParam == hwndMonSel)
+                       {
+                               if (pt.x == -1 && pt.y == -1)
+                               {
+                                       RECT rcMon;
+
+                                       Index = (INT)SendMessage(hwndMonSel,
+                                                                MSLM_GETCURSEL,
+                                                                0,
+                                                                0);
+
+                                       if (Index >= 0 &&
+                                           (INT)SendMessage(hwndMonSel,
+                                                            MSLM_GETMONITORRECT,
+                                                            Index,
+                                                            (LPARAM)&rcMon) > 0)
+                                       {
+                                               pt.x = rcMon.left + ((rcMon.right - rcMon.left) / 2);
+                                               pt.y = rcMon.top + ((rcMon.bottom - rcMon.top) / 2);
+                                       }
+                                       else
+                                               pt.x = pt.y = 0;
+       
+                                       MapWindowPoints(hwndMonSel,
+                                                       NULL,
+                                                       &pt,
+                                                       1);
+                               }
+                               else
+                               {
+                                       ptClient = pt;
+                                       MapWindowPoints(NULL,
+                                                       hwndMonSel,
+                                                       &ptClient,
+                                                       1);
+
+                                       Index = (INT)SendMessage(hwndMonSel,
+                                                                MSLM_HITTEST,
+                                                                (WPARAM)&ptClient,
+                                                                0);
+                               }
 
+                               if (Index >= 0)
+                               {
+                                       hPopup = LoadPopupMenu(hApplet,
+                                                              MAKEINTRESOURCE(IDM_MONITOR_MENU));
+                                       if (hPopup != NULL)
+                                       {
+                                               /* FIXME: Enable/Disable menu items */
+                                               EnableMenuItem(hPopup,
+                                                              ID_MENU_ATTACHED,
+                                                              MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+                                               EnableMenuItem(hPopup,
+                                                              ID_MENU_PRIMARY,
+                                                              MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+                                               EnableMenuItem(hPopup,
+                                                              ID_MENU_IDENTIFY,
+                                                              MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+                                               EnableMenuItem(hPopup,
+                                                              ID_MENU_PROPERTIES,
+                                                              MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+
+                                               uiCmd = (UINT)TrackPopupMenu(hPopup,
+                                                                            TPM_RETURNCMD | TPM_RIGHTBUTTON,
+                                                                            pt.x,
+                                                                            pt.y,
+                                                                            0,
+                                                                            hwndDlg,
+                                                                            NULL);
+
+                                               switch (uiCmd)
+                                               {
+                                                       case ID_MENU_ATTACHED:
+                                                       case ID_MENU_PRIMARY:
+                                                       case ID_MENU_IDENTIFY:
+                                                       case ID_MENU_PROPERTIES:
+                                                               /* FIXME: Implement */
+                                                               break;
+                                               }
+
+                                               DestroyMenu(hPopup);
+                                       }
+                               }
+                       }
                        break;
                }
 
                case WM_DESTROY:
                {
-                       PDISPLAY_DEVICE_ENTRY Current = DisplayDeviceList;
+                       DWORD i;
+                       PDISPLAY_DEVICE_ENTRY Current = pGlobalData->DisplayDeviceList;
+
                        while (Current != NULL)
                        {
                                PDISPLAY_DEVICE_ENTRY Next = Current->Flink;
@@ -606,7 +849,13 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar
                                Current = Next;
                        }
 
-                       DeleteObject(hBitmap);
+                       for (i = 0; i < NUM_SPECTRUM_BITMAPS; i++)
+                       {
+                               if (pGlobalData->hSpectrumBitmaps[i])
+                                       DeleteObject(pGlobalData->hSpectrumBitmaps[i]);
+                       }
+
+                       HeapFree(GetProcessHeap(), 0, pGlobalData);
                }
        }
        return FALSE;