Author: weiden
Date: Thu Sep 27 21:53:14 2007
New Revision: 29252
URL: 
http://svn.reactos.org/svn/reactos?rev=29252&view=rev
Log:
- Display a list of monitors if there's more than one monitor
- Display a list of available refresh rates for the current mode
Modified:
    trunk/reactos/dll/win32/shellext/deskmon/deskmon.c
    trunk/reactos/dll/win32/shellext/deskmon/deskmon.h
    trunk/reactos/dll/win32/shellext/deskmon/lang/en-US.rc
    trunk/reactos/dll/win32/shellext/deskmon/resource.h
Modified: trunk/reactos/dll/win32/shellext/deskmon/deskmon.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shellext/deskmon…
==============================================================================
--- trunk/reactos/dll/win32/shellext/deskmon/deskmon.c (original)
+++ trunk/reactos/dll/win32/shellext/deskmon/deskmon.c Thu Sep 27 21:53:14 2007
@@ -5,26 +5,341 @@
 static HINSTANCE hInstance;
+#if 0
+#ifdef UNICODE
+typedef INT_PTR (WINAPI *PDEVICEPROPERTIES)(HWND,LPCWSTR,LPCWSTR,BOOL);
+#define FUNC_DEVICEPROPERTIES "DevicePropertiesW"
+#else
+typedef INT_PTR (WINAPI *PDEVICEPROPERTIES)(HWND,LPCWSTR,LPCSTR,BOOL);
+#define FUNC_DEVICEPROPERTIES "DevicePropertiesA"
+#endif
+
+static VOID
+ShowMonitorProperties(PDESKMONITOR This,
+                      LPCTSTR lpDevice)
+{
+    HMODULE hDevMgr;
+    PDEVICEPROPERTIES pDeviceProperties;
+
+    hDevMgr = LoadLibrary(TEXT("devmgr.dll"));
+    if (hDevMgr != NULL)
+    {
+        pDeviceProperties = (PDEVICEPROPERTIESW)GetProcAddress(hDevMgr,
+                                                               FUNC_DEVICEPROPERTIES);
+        if (pDeviceProperties != NULL)
+        {
+            pDeviceProperties(This->hwndDlg,
+                               NULL,
+                               lpDevice,
+                               FALSE);
+        }
+
+        FreeLibrary(hDevMgr);
+    }
+}
+#endif
+
+static VOID
+UpdateMonitorDialogControls(PDESKMONITOR This)
+{
+    PDEVMODEW lpCurrentMode, lpMode;
+    DWORD dwIndex = 0;
+    TCHAR szBuffer[64];
+    BOOL bHasDef = FALSE;
+    INT i;
+
+    /* Fill the refresh rate combo box */
+    SendDlgItemMessage(This->hwndDlg,
+                       IDC_REFRESHRATE,
+                       CB_RESETCONTENT,
+                       0,
+                       0);
+
+    lpCurrentMode =
This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
+
+    do
+    {
+        lpMode =
This->DeskExtInterface->EnumAllModes(This->DeskExtInterface->Context,
+                                                      dwIndex++);
+        if (lpMode != NULL &&
+            lpMode->dmBitsPerPel == lpCurrentMode->dmBitsPerPel &&
+            lpMode->dmPelsWidth == lpCurrentMode->dmPelsWidth &&
+            lpMode->dmPelsHeight == lpCurrentMode->dmPelsHeight)
+        {
+            /* We're only interested in refresh rates for the current resolution and
color depth */
+
+            if (lpMode->dmDisplayFrequency <= 1)
+            {
+                /* Default hardware frequency */
+                if (bHasDef)
+                    continue;
+
+                bHasDef = TRUE;
+
+                if (!LoadString(hInstance,
+                                IDS_USEDEFFRQUENCY,
+                                szBuffer,
+                                sizeof(szBuffer) / sizeof(szBuffer[0])))
+                {
+                    szBuffer[0] = TEXT('\0');
+                }
+            }
+            else
+            {
+                TCHAR szFmt[64];
+
+                if (!LoadString(hInstance,
+                                IDS_FREQFMT,
+                                szFmt,
+                                sizeof(szFmt) / sizeof(szFmt[0])))
+                {
+                    szFmt[0] = TEXT('\0');
+                }
+
+                _sntprintf(szBuffer,
+                           sizeof(szBuffer) / sizeof(szBuffer[0]),
+                           szFmt,
+                           lpMode->dmDisplayFrequency);
+            }
+
+            i = (INT)SendDlgItemMessage(This->hwndDlg,
+                                        IDC_REFRESHRATE,
+                                        CB_ADDSTRING,
+                                        0,
+                                        (LPARAM)szBuffer);
+            if (i >= 0)
+            {
+                SendDlgItemMessage(This->hwndDlg,
+                                   IDC_REFRESHRATE,
+                                   CB_SETITEMDATA,
+                                   (WPARAM)lpMode,
+                                   0);
+
+                if (lpMode->dmDisplayFrequency ==
lpCurrentMode->dmDisplayFrequency)
+                {
+                    SendDlgItemMessage(This->hwndDlg,
+                                       IDC_REFRESHRATE,
+                                       CB_SETCURSEL,
+                                       (WPARAM)i,
+                                       0);
+                }
+            }
+        }
+
+    } while (lpMode != NULL);
+
+    /* FIXME: Update pruning mode controls */
+
+    /* FIXME: Enable/Disable properties button */
+    EnableWindow(GetDlgItem(This->hwndDlg,
+                            IDC_MONITORPROPERTIES),
+                 FALSE);
+}
+
 static VOID
 InitMonitorDialog(PDESKMONITOR This)
 {
-    LPTSTR lpMonitorName;
-
-    lpMonitorName = QueryDeskCplString(This->pdtobj,
-                                       RegisterClipboardFormat(DESK_EXT_MONITORNAME));
-    if (lpMonitorName != NULL)
-    {
+    PDESKMONINFO pmi, pminext, *pmilink;
+    DISPLAY_DEVICE dd;
+    BOOL bRet;
+    INT i;
+    DWORD dwIndex = 0;
+
+    /* Free all allocated monitors */
+    pmi = This->Monitors;
+    This->Monitors = NULL;
+    while (pmi != NULL)
+    {
+        pminext = pmi->Next;
+        LocalFree((HLOCAL)pmi);
+        pmi = pminext;
+    }
+
+    This->SelMonitor = NULL;
+    This->dwMonitorCount = 0;
+
+    if (This->lpDisplayDevice != NULL)
+        LocalFree((HLOCAL)This->lpDisplayDevice);
+
+    This->lpDisplayDevice = QueryDeskCplString(This->pdtobj,
+
RegisterClipboardFormat(DESK_EXT_DISPLAYDEVICE));
+
+    if (This->DeskExtInterface != NULL)
+    {
+        if (This->lpDisplayDevice != NULL)
+        {
+            /* Enumerate all monitors */
+            pmilink = &This->Monitors;
+
+            do
+            {
+                dd.cb = sizeof(dd);
+                bRet = EnumDisplayDevices(This->lpDisplayDevice,
+                                          dwIndex++,
+                                          &dd,
+                                          0);
+                if (bRet)
+                {
+                    pmi = LocalAlloc(LMEM_FIXED,
+                                     sizeof(*pmi));
+                    if (pmi != NULL)
+                    {
+                        CopyMemory(&pmi->dd,
+                                   &dd,
+                                   sizeof(dd));
+                        pmi->Next = NULL;
+                        *pmilink = pmi;
+                        pmilink = &pmi->Next;
+
+                        This->dwMonitorCount++;
+                    }
+                }
+            } while (bRet);
+        }
+
+        This->lpDevModeOnInit =
This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
+    }
+    else
+        This->lpDevModeOnInit = NULL;
+
+    /* Setup the UI depending on how many monitors are attached */
+    if (This->dwMonitorCount == 0)
+    {
+        LPTSTR lpMonitorName;
+
+        /* This is a fallback, let's hope that desk.cpl can provide us with a monitor
name */
+        lpMonitorName = QueryDeskCplString(This->pdtobj,
+
RegisterClipboardFormat(DESK_EXT_MONITORNAME));
+
         SetDlgItemText(This->hwndDlg,
                        IDC_MONITORNAME,
                        lpMonitorName);
-        LocalFree((HLOCAL)lpMonitorName);
-    }
+        if (lpMonitorName != NULL)
+            LocalFree((HLOCAL)lpMonitorName);
+    }
+    else if (This->dwMonitorCount == 1)
+    {
+        This->SelMonitor = This->Monitors;
+        SetDlgItemText(This->hwndDlg,
+                       IDC_MONITORNAME,
+                       This->Monitors->dd.DeviceString);
+    }
+    else
+    {
+        SendDlgItemMessage(This->hwndDlg,
+                           IDC_MONITORLIST,
+                           LB_RESETCONTENT,
+                           0,
+                           0);
+
+        pmi = This->Monitors;
+        while (pmi != NULL)
+        {
+            i = (INT)SendDlgItemMessage(This->hwndDlg,
+                                        IDC_MONITORLIST,
+                                        LB_ADDSTRING,
+                                        0,
+                                        (LPARAM)pmi->dd.DeviceString);
+            if (i >= 0)
+            {
+                SendDlgItemMessage(This->hwndDlg,
+                                   IDC_MONITORLIST,
+                                   LB_SETITEMDATA,
+                                   (WPARAM)i,
+                                   (LPARAM)pmi);
+
+                if (This->SelMonitor == NULL)
+                {
+                    SendDlgItemMessage(This->hwndDlg,
+                                       IDC_MONITORLIST,
+                                       LB_SETCURSEL,
+                                       (WPARAM)i,
+                                       0);
+
+                    This->SelMonitor = pmi;
+                }
+            }
+
+            pmi = pmi->Next;
+        }
+    }
+
+    /* Show/Hide controls */
+    ShowWindow(GetDlgItem(This->hwndDlg,
+                          IDC_MONITORNAME),
+               (This->dwMonitorCount <= 1 ? SW_SHOW : SW_HIDE));
+    ShowWindow(GetDlgItem(This->hwndDlg,
+                          IDC_MONITORLIST),
+               (This->dwMonitorCount > 1 ? SW_SHOW : SW_HIDE));
+
+    UpdateMonitorDialogControls(This);
+}
+
+static LONG
+ApplyMonitorChanges(PDESKMONITOR This)
+{
+    LONG lChangeRet;
     if (This->DeskExtInterface != NULL)
     {
-        /* FIXME */
-    }
+        /* Change the display settings through desk.cpl */
+        lChangeRet = DeskCplExtDisplaySaveSettings(This->DeskExtInterface,
+                                                   This->hwndDlg);
+        if (lChangeRet == DISP_CHANGE_SUCCESSFUL)
+        {
+            /* Save the new mode */
+            This->lpDevModeOnInit =
This->DeskExtInterface->GetCurrentMode(This->DeskExtInterface->Context);
+            return PSNRET_NOERROR;
+        }
+        else if (lChangeRet == DISP_CHANGE_RESTART)
+        {
+            /* Notify desk.cpl that the user needs to reboot */
+            PropSheet_RestartWindows(GetParent(This->hwndDlg));
+            return PSNRET_NOERROR;
+        }
+    }
+
+    InitMonitorDialog(This);
+
+    return PSNRET_INVALID_NOCHANGEPAGE;
+}
+
+static VOID
+ResetMonitorChanges(PDESKMONITOR This)
+{
+    if (This->DeskExtInterface != NULL && This->lpDevModeOnInit != NULL)
+    {
+
This->DeskExtInterface->SetCurrentMode(This->DeskExtInterface->Context,
+                                               This->lpDevModeOnInit);
+    }
+}
+
+static BOOL
+UpdateMonitorSelection(PDESKMONITOR This)
+{
+    INT i;
+
+    if (This->dwMonitorCount <= 1)
+        return FALSE;
+
+    i = (INT)SendDlgItemMessage(This->hwndDlg,
+                                IDC_MONITORLIST,
+                                LB_GETCURSEL,
+                                0,
+                                0);
+    if (i >= 0)
+    {
+        This->SelMonitor = (PDESKMONINFO)SendDlgItemMessage(This->hwndDlg,
+                                                            IDC_MONITORLIST,
+                                                            LB_GETITEMDATA,
+                                                            (WPARAM)i,
+                                                            0);
+    }
+    else
+        This->SelMonitor = NULL;
+
+    return TRUE;
 }
 static INT_PTR CALLBACK
@@ -60,9 +375,37 @@
             {
                 case IDC_MONITORPROPERTIES:
                     break;
+
+                case IDC_MONITORLIST:
+                    if (HIWORD(wParam) == LBN_SELCHANGE)
+                    {
+                        if (UpdateMonitorSelection(This))
+                            UpdateMonitorDialogControls(This);
+                    }
+                    break;
             }
-
             break;
+
+        case WM_NOTIFY:
+        {
+            NMHDR *nmh = (NMHDR *)lParam;
+
+            switch (nmh->code)
+            {
+                case PSN_APPLY:
+                {
+                    SetWindowLong(hwndDlg,
+                                  DWL_MSGRESULT,
+                                  ApplyMonitorChanges(This));
+                    break;
+                }
+
+                case PSN_RESET:
+                    ResetMonitorChanges(This);
+                    break;
+            }
+            break;
+        }
     }
     return Ret;
@@ -71,6 +414,8 @@
 static VOID
 IDeskMonitor_Destroy(PDESKMONITOR This)
 {
+    PDESKMONINFO pmi, pminext;
+
     if (This->pdtobj != NULL)
     {
         IDataObject_Release(This->pdtobj);
@@ -81,6 +426,22 @@
     {
         LocalFree((HLOCAL)This->DeskExtInterface);
         This->DeskExtInterface = NULL;
+    }
+
+    if (This->lpDisplayDevice != NULL)
+    {
+        LocalFree((HLOCAL)This->lpDisplayDevice);
+        This->lpDisplayDevice = NULL;
+    }
+
+    /* Free all monitors */
+    pmi = This->Monitors;
+    This->Monitors = NULL;
+    while (pmi != NULL)
+    {
+        pminext = pmi->Next;
+        LocalFree((HLOCAL)pmi);
+        pmi = pminext;
     }
 }
Modified: trunk/reactos/dll/win32/shellext/deskmon/deskmon.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shellext/deskmon…
==============================================================================
--- trunk/reactos/dll/win32/shellext/deskmon/deskmon.h (original)
+++ trunk/reactos/dll/win32/shellext/deskmon/deskmon.h Thu Sep 27 21:53:14 2007
@@ -1,5 +1,11 @@
 #ifndef __DESKMON__H
 #define __DESKMON__H
+
+typedef struct _DESKMONINFO
+{
+    DISPLAY_DEVICE dd;
+    struct _DESKMONINFO *Next;
+} DESKMONINFO, *PDESKMONINFO;
 typedef struct _DESKMONITOR
 {
@@ -11,6 +17,11 @@
     HWND hwndDlg;
     PDESK_EXT_INTERFACE DeskExtInterface;
     IDataObject *pdtobj;
+    LPTSTR lpDisplayDevice;
+    DWORD dwMonitorCount;
+    PDESKMONINFO Monitors;
+    PDESKMONINFO SelMonitor;
+    PDEVMODEW lpDevModeOnInit;
 } DESKMONITOR, *PDESKMONITOR;
 extern LONG dll_refs;
Modified: trunk/reactos/dll/win32/shellext/deskmon/lang/en-US.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shellext/deskmon…
==============================================================================
--- trunk/reactos/dll/win32/shellext/deskmon/lang/en-US.rc (original)
+++ trunk/reactos/dll/win32/shellext/deskmon/lang/en-US.rc Thu Sep 27 21:53:14 2007
@@ -7,6 +7,16 @@
 BEGIN
   GROUPBOX "Monitor type", -1, 7, 3, 237, 52
   LTEXT "", IDC_MONITORNAME, 40, 17, 190, 20, SS_NOPREFIX
+  LISTBOX IDC_MONITORLIST, 40, 13, 196, 30, WS_VSCROLL
   PUSHBUTTON "&Properties", IDC_MONITORPROPERTIES, 177, 35, 59, 14,
WS_DISABLED
+  GROUPBOX "Monitor settings", IDS_MONITORSETTINGSGROUP, 7, 58, 237, 47
+  LTEXT "&Screen refresh rate:", IDS_REFRESHRATELABEL, 13, 73, 225, 8
+  COMBOBOX IDC_REFRESHRATE, 13, 85, 225, 200, WS_VSCROLL | CBS_DROPDOWNLIST | CBS_SORT
 END
+STRINGTABLE
+BEGIN
+  IDS_USEDEFFRQUENCY "Use hardware default setting"
+  IDS_FREQFMT "%u Hertz"
+END
+
Modified: trunk/reactos/dll/win32/shellext/deskmon/resource.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shellext/deskmon…
==============================================================================
--- trunk/reactos/dll/win32/shellext/deskmon/resource.h (original)
+++ trunk/reactos/dll/win32/shellext/deskmon/resource.h Thu Sep 27 21:53:14 2007
@@ -4,6 +4,13 @@
 #define IDD_MONITOR  100
 #define IDC_MONITORNAME 201
-#define IDC_MONITORPROPERTIES 202
+#define IDC_MONITORLIST 202
+#define IDC_MONITORPROPERTIES 203
+#define IDS_MONITORSETTINGSGROUP 204
+#define IDS_REFRESHRATELABEL 205
+#define IDC_REFRESHRATE 206
+
+#define IDS_USEDEFFRQUENCY 101
+#define IDS_FREQFMT 102
 #endif /* __RESOURCE__H */