//***************************************************************************
//
//    QuickRes for Windows NT and Windows 9x
//
//    Tray app to change your display resolution quickly.
//
//    written by ToddLa
//
//    03/03/96 - ChrisW : Get to build on NT
//    03/28/96 - MDesai : Finish porting; add submenus with frequencies;
//                        Test for valid devmode.
//    04/23/96 - MDesai : option for 'showing tested modes only'
//    10/01/96 - MDesai : fix all win95-specific bugs
//    11/03/98 - MDesai : 'multimonitor aware'
//    12/02/99 - MDesai : better multimon support
//
//***************************************************************************


#include "QuickRes.h"


PTCHAR szAppName;

HINSTANCE    hInstApp;
HICON        AppIcon;


//
// options, properties, about and exit...
// monitor menu
//

HMENU        MainMenu;
HMENU        MonitorMenu=NULL;

//
// number of monitors/display devices installed
// pointer to monitorinfo struct for each monitor
//

INT              iMonitors;
LPQRMONITORINFO  pMonitors;


//
// Waiting for a Popup - don't process any tray messages
//

BOOL Waiting=FALSE;


//
//  Flags: update registry, show restart modes, sort order
//         also where the freq menu(s) go.
//
WORD QuickResFlags;
WORD FreqMenuLocation;


//
//   Function pointers for NT5
//
FARPROC   lpfnEDSEx=NULL;
FARPROC   lpfnEDD=NULL;


//
//***************************************************************************
//
//  GetResourceString( UINT )
//
//  Load a resource string into a LPTSTR - the memory for the string
//  is dynamically allocated.  The callee must free the memory!
//
//***************************************************************************
//

LPTSTR GetResourceString ( UINT ResourceID )
{


    INT    BuffSize=RESOURCE_STRINGLEN;     // current max size of string
    PTCHAR BigBuf;                          // buffer to find size of resource
    PTCHAR ResBuf;                          // buffer for resource
    INT    len;                             // length of the resource


    while (1)
    {

        //
        //  Allocate hopefully oversized buffer
        //

        if( !(BigBuf= LocalAlloc( LPTR, BuffSize ) ) )
        {
            return NULL;
        }


        //
        //  Try to read string into BigBuf to get its length
        //

        if ( !(len = LoadString(hInstApp, ResourceID, BigBuf, BuffSize)) )
        {
            return NULL;
        }


        //
        //  Buffer is too small - try again.
        //

        if( len >= BuffSize-1 )
        {
            BuffSize <<= 1;
            LocalFree ( BigBuf );
        }

        else
        {

            //
            //  Reallocate properly sized string buffer,
            //  and copy string into it
            //

            len = ( len + 1 ) * sizeof( TCHAR );

            if (ResBuf = LocalAlloc( LPTR, len ))
            {
                lstrcpyn ( ResBuf, BigBuf, len );
            }

            LocalFree ( BigBuf );

            return( ResBuf );

        }

    }

}


//
//***************************************************************************
//
// GetModeName( PDEVMODE, PTCHAR*, PTCHAR* )
//
// Translate devmode into user friendly strings-
// one for resolution and color depth; one for refresh rate
//
//***************************************************************************
//

void GetModeName(PDEVMODE pDevMode, PTCHAR *szMode, PTCHAR *szFreq )
{

    PTCHAR FmtRes=NULL;             // Format strings for
    PTCHAR FmtHz=NULL;              // resolution and Hz


    //
    // Load format string corresponding to devmode
    //

    FmtRes = GetResourceString ( IDS_CRES + BPP(pDevMode) );


    //
    // Use Default Freq string if necessary
    //
    if (fShowFreqs)
    {
        if( HZ(pDevMode) == 0 || HZ(pDevMode) == 1)
        {
            FmtHz = GetResourceString ( IDS_DEFHERTZ );
        }
        else
        {
            FmtHz = GetResourceString ( IDS_HERTZ );
        }
    }

    //
    //  return separate resolution and frequency strings
    //  need to convert "%d"-> "12345", add byte for '\0'
    //

    if (FmtRes)
    {
        if (*szMode = LocalAlloc( LPTR, sizeof(TCHAR)*
                                (lstrlen(FmtRes)+2*INT_FORMAT_TO_5_DIGITS+1 ) ))
        {
            wsprintf(*szMode, FmtRes, XRES(pDevMode), YRES(pDevMode) );
        }

        LocalFree ( FmtRes );
    }


    if (fShowFreqs && FmtHz)
    {

        if (*szFreq = LocalAlloc ( LPTR, sizeof(TCHAR)*
                                   (lstrlen(FmtHz)+INT_FORMAT_TO_5_DIGITS+1) ))
        {
            wsprintf(*szFreq, FmtHz, HZ(pDevMode));
        }

        LocalFree ( FmtHz );
    }

}



//
//***************************************************************************
//
//   GetCurrentDevMode( INT, PDEVMODE )
//
//   Get a pointer to the current devmode into *pDM
//
//***************************************************************************
//

PDEVMODE GetCurrentDevMode(INT iDisplay, PDEVMODE pDM)
{

    UINT uRet=0;

    pDM->dmSize= sizeof(DEVMODE);

    //
    // NT specific; returns current devmode
    //

    if (fShowFreqs)
    {
        uRet = EnumDisplaySettings( pMonitors[iDisplay].DeviceName, (DWORD)ENUM_CURRENT_SETTINGS, pDM);
    }

    if (!uRet)
    {
        //
        //  ENUM_CURRENT_SETTINGS doesnt work on win95
        //  Get current settings via GetDeviceCaps
        //

        HDC  hDC;
        UINT HorzRes;
        UINT VertRes;
        UINT BPP;
        UINT VRefresh;
        UINT Index;

        hDC      =  GetDC( NULL );
        HorzRes  =  GetDeviceCaps( hDC, HORZRES );
        VertRes  =  GetDeviceCaps( hDC, VERTRES );
        BPP      =  GetDeviceCaps( hDC, BITSPIXEL ) * GetDeviceCaps( hDC, PLANES );
        VRefresh =  GetDeviceCaps( hDC, VREFRESH );

        //
        //  Enumerate all settings until one matches our current settings
        //

        for ( Index=0;
              EnumDisplaySettings( pMonitors[iDisplay].DeviceName, Index, pDM);
              Index++ )
        {
            if ( HorzRes ==  XRES(pDM) &&
                 VertRes ==  YRES(pDM) &&
                 BPP     ==  BPP(pDM)
               )
            {
                //
                // if frequency matters, then check for it
                //

                if (!fShowFreqs || (VRefresh == HZ(pDM)) )
                    break;
            }
        }

        ReleaseDC (NULL, hDC);
    }

    return pDM;
}



//
//***************************************************************************
//
//  SetMode( HWND, UINT )
//
//  Set the new devmode and update registry on request using
//  the CDS_UPDATEREGISTRY flag.  If user wants to change and
//  restart, then we need to update the registry and restart.
//
//***************************************************************************
//

BOOL SetMode( HWND hwnd, INT iDisplay, UINT index )
{
    DWORD    CDSret=0;                  // ret value, ChangeDisplaySettings
    DWORD    CDSFlags=0;                // 2nd param of call to CDS
    INT_PTR  DialogBoxRet=0;            // IDYES/NO/ABORT/CANCEL
    LPDEVMODEINFO pSave;                // save ptr in iDisplay to remember orig mode
    LPDEVMODEINFO pdm;                  // new mode to be set
    BOOL     bChange=FALSE;             // changing modes or not
    LPQRMONITORINFO pCurrMon;           // ptr to current monitorinfo strcut


    pCurrMon = &pMonitors[iDisplay];

    //
    //  Save current mode; find ptr to new mode
    //

    pSave = pCurrMon->pCurrentdm;
    pdm   = &(pCurrMon->pModes[index]);

    //
    //  If user wants to update registry
    //

    if( fUpdateReg )
    {
        CDSFlags |= CDS_UPDATEREGISTRY;
    }


    //
    //  Tell CDS what fields may be changing
    //  Also, keep appwndproc from doing anything while we are testing
    //

    pdm->dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
    Waiting=TRUE;


    //
    //  Call CDS and update registry on request.  (If it is
    //  a known bad mode give user chance to change his mind.)
    //

    if( (VALIDMODE(pdm) != MODE_INVALID ) ||
           ( MsgBox( IDS_INVALIDMODE, 0, MB_YESNO | MB_ICONQUESTION )==IDYES ) )
    {

        CDSret = ChangeDisplaySettingsEx( pCurrMon->DeviceName, &(pdm->dm), NULL, CDSFlags, 0);

        if (CDSret == DISP_CHANGE_SUCCESSFUL)
        {
            //
            //  Even though it may be temporary, current dm has changed.
            //  Need to reset pCurrentdm to point to new current DM.
            //  Change tooltip to reflect old settings
            //

            pCurrMon->pCurrentdm = pdm;

            TrayMessage(hwnd, NIM_MODIFY, TRAY_ID, AppIcon);

            //
            //  Return value claims that it 'worked.' But, it may not visible
            //  to the user (e.g. the mode is unsupported by the monitor).
            //  If the User has not already approved this new resolution,
            //  then make the user approve the change, or we default back to
            //  the last devmode.
            //

            if ( fGoodMode(pdm) )
            {
                //
                //  VALID or BESTHZ modes - go ahead and change
                //

                bChange = TRUE;
            }

            else
            {
                //
                //  Ask user if it looks okay
                //  Flag the mode based on return value.
                //

                switch( DialogBoxRet = DialogBoxParam( hInstApp,
                                          MAKEINTRESOURCE(KeepNewRes),
                                          NULL,
                                          KeepNewResDlgProc,
                                          iDisplay) )
                {

                                    //
                                    //  There should NOT be a break after
                                    //  IDYES.  Fall thru by design.
                                    //
                    case IDYES:     bChange = TRUE;

                    case IDABORT:   VALIDMODE(pdm) = MODE_VALID;
                                    break;

                    case IDNO:
                    case IDCANCEL:  VALIDMODE(pdm) = MODE_INVALID;
                                    break;

                }   // switch

            }   //  else - MODE_INVALID

        }

        if (CDSret != DISP_CHANGE_SUCCESSFUL)
        {
            //
            // Requires restart.  Ask user if thats okay.
            //

            if (CDSret == DISP_CHANGE_RESTART)
            {

                if ( MsgBox(IDS_RESTART, 0, MB_YESNO | MB_ICONQUESTION) == IDYES )
                {

                    //
                    //  After restart all modes will need to be tested again?
                    //

                    SetDevmodeFlags ( iDisplay, TRUE );


                    //
                    //  Call CDS again to update registry
                    //

                    ChangeDisplaySettingsEx( pCurrMon->DeviceName, &(pdm->dm), NULL,
                                             (CDSFlags | CDS_UPDATEREGISTRY), 0);

                    ExitWindowsEx(EWX_REBOOT, 0);
                }

            }
            else
            {

                 //
                 // Tell user we cannot change to this devmode
                 //

                 MsgBox(IDS_CANTSETMODE, 0, MB_OK | MB_ICONEXCLAMATION);
            }

        }   // end else != DISP_CHANGE_SUCCESSFUL


        if (bChange)
        {
            //
            //  Changing to a valid mode; destroy and rebuild menu
            //  Mark mode we were just in as valid (if it wasnt already)
            //

            VALIDMODE(pSave) |= MODE_VALID;

            //
            //  This is the new "Best Hz" mode.  The old mode is 'only valid'.
            //

            if ((FreqMenuLocation == IDD_ONEMENUMOBILE) ||
                (FreqMenuLocation == IDD_ONEMENUBOTTOM) )
            {
                VALIDMODE(pCurrMon->pCurrentdm) = MODE_BESTHZ;
            }

            DestroyModeMenu( iDisplay, TRUE, FALSE );
        }

        else    // !bChange
        {

            //
            //  Change back to last good devmode; do not have to recheck menuitems
            //

            pCurrMon->pCurrentdm = pSave;


            //
            //  Change back, and reset registry IF we had set it above
            //  Change tooltip to reflect old settings
            //

            if (CDSret != DISP_CHANGE_RESTART)
            {
                ChangeDisplaySettingsEx( pCurrMon->DeviceName, &(pCurrMon->pCurrentdm->dm),
                                         NULL, CDSFlags, 0);
            }

            TrayMessage(hwnd, NIM_MODIFY, TRAY_ID, AppIcon);

        }  // bChange


    }  // endif


    //
    //  Save new settings for this devmode to the registry.
    //  Even if quickres does not exit gracefully, preferences
    //  will be saved.
    //

    if (fRememberModes)
    {
        SaveAllSettings();
    }

    //
    //  Show modemenu again; allow appwndproc to process messages
    //

    if (!bChange)
    {
        SetTimer(hwnd, TRAY_ID, 10, NULL);
    }

    Waiting=FALSE;


    //
    // if Current hasnt changed then we return false
    //

    return (bChange);

}


//
//********************************************************************
//
//  CompareDevmodes ( LPDEVMODEINFO, LPDEVMODEINFO )
//
//  Compares 2 devmodes -
//  Returns 0 if equal, -1 if first > second, +1 if first < second
//
//  msb to lsb: xres, yres, bpp, hertz
//********************************************************************
//

int _cdecl CompareDevmodes( LPDEVMODEINFO pDmi1, LPDEVMODEINFO pDmi2 )
{
    INT compare;
    LPDEVMODE pDm1 = &(pDmi1->dm);
    LPDEVMODE pDm2 = &(pDmi2->dm);


    //
    //  Compare Xs, then Ys, BPP, and Hz.  If !fShowFreqs
    //  then compare only Xs, Ys, and BPP.
    //

    if ( !fSortByBPP || ((compare= BPP(pDm1) - BPP(pDm2)) == 0))
    {
        if( (compare= ( XRES(pDm1) - XRES(pDm2) ) ) == 0 )
        {
            if( (compare= ( YRES(pDm1) - YRES(pDm2) ) ) == 0 )
            {
                if ( fSortByBPP || ((compare= BPP(pDm1) - BPP(pDm2)) == 0))
                {
                   compare = fShowFreqs ? (HZ(pDm1) - HZ(pDm2))  :  0;
                }
            }
        }
    }

    //
    //  Set return value as -1, 0, or 1 only
    //

    if( compare < 0)
    {
        compare= -1;
    }

    else
    {
        if( compare > 0 )
        {
            compare= 1;
        }
    }

    return( compare );

}


//
//********************************************************************
//
//  CheckMenuItemCurrentMode ( INT )
//
//  Traverse all menu items and check the Hz value corresponding
//  to the current mode.  Also, highlight the current resolution/
//  BPP as defaultmenuitem
//
//********************************************************************
//

void CheckMenuItemCurrentMode( INT iDisplay )
{

    int i;                          //  counter
    DEVMODEINFO dmi;                //  temporary storage for current DM
    LPQRMONITORINFO lpqrmi;         //  temporary ptr
    HMENU hMenu;                    //  Frequency submenu for a given Res/BPP
    UINT  MenuItem;                 //  Menu item for exact devmode
    DWORD dwSta;                    //  returns status variable



    lpqrmi = &pMonitors[iDisplay];

    //
    // Need a pointer to the current devmode.  This function will search
    // pModes trying to match the devmode pointed to by pCurrentdm.
    // After the 1st time through, pCurrentdm will be a ptr IN pModes
    //

    if (!lpqrmi->pCurrentdm)
    {
        //
        // Get current devmode
        //

        GetCurrentDevMode(iDisplay, &(dmi.dm));
        lpqrmi->pCurrentdm = &dmi;
    }


    //
    // Uncheck all menu items
    //

    for( i=0; i<lpqrmi->iModes; i++ )
    {

        hMenu = lpqrmi->FreqMenu[FREQMENU( &lpqrmi->pModes[i] )];

        MenuItem= MENUITEM( &lpqrmi->pModes[i] );

        //
        //  Uncheck the Hz in the FreqMenu (if applicable); uncheck item on mode menu
        //

        if (hMenu)
        {
            dwSta= CheckMenuItem(hMenu, MenuItem, MF_BYCOMMAND|MF_UNCHECKED);
            CheckMenuItem(lpqrmi->ModeMenu, FREQMENU( &lpqrmi->pModes[i] ), MF_BYPOSITION  | MF_UNCHECKED );
        }

        CheckMenuItem(lpqrmi->ModeMenu, MenuItem, MF_BYCOMMAND  | MF_UNCHECKED );
    }



    //
    // Check the current one
    //

    for( i=0; i<lpqrmi->iModes; i++ )
    {

        //
        // Go through the array looking for a match of the current devmode
        //

        if( ( CompareDevmodes( lpqrmi->pCurrentdm, &lpqrmi->pModes[i] ) ) == 0 )
        {

            //
            //  Found it!
            //  Get the menu item ID for this devmode and which
            //  frequency submenu it is a part of.
            //

            hMenu = lpqrmi->FreqMenu[FREQMENU( &lpqrmi->pModes[i] )];
            MenuItem= MENUITEM( &lpqrmi->pModes[i] );


            //
            // Save this ptr in the pCurrentdm variable
            // check menu item on mode menu and check mode
            // on frequency submenu (if applicable)
            //

            lpqrmi->pCurrentdm = &lpqrmi->pModes[i];

            if (hMenu)
            {
                dwSta= CheckMenuItem(hMenu, MenuItem, MF_BYCOMMAND|MF_CHECKED);
                CheckMenuItem(lpqrmi->ModeMenu, FREQMENU(&lpqrmi->pModes[i]), MF_BYPOSITION | MF_CHECKED );
            }
            else
            {
                CheckMenuItem(lpqrmi->ModeMenu, MenuItem, MF_BYCOMMAND  | MF_CHECKED );
            }

            break;
        }
    }
}


//
//********************************************************************
//
//   DestroyModeMenu( INT iDisplay, BOOL bRebuild, BOOL bNeedtoSort )
//
//   Free all frequency submenus and the mode menu
//
//********************************************************************
//

void DestroyModeMenu( INT iDisplay, BOOL bRebuild, BOOL bNeedtoSort)
{

    int i;
    LPQRMONITORINFO lpqrmi;         //  temporary ptr



    lpqrmi = &pMonitors[iDisplay];

    //
    //  Free all frequency submenus
    //

    for ( i = 0; i < lpqrmi->iModes; i++ )
    {

        if (IsMenu(lpqrmi->FreqMenu[i]))
        {
            DestroyMenu( lpqrmi->FreqMenu[i] );
            lpqrmi->FreqMenu[i] = NULL;
        }

    }


    //
    //  Free the mode menu (resolutions/BPP)
    //

    if (lpqrmi->ModeMenu)
    {
        DestroyMenu(lpqrmi->ModeMenu);
        lpqrmi->ModeMenu = NULL;

        if (iMonitors==1)
        {
            DestroyMenu(MonitorMenu);
            MonitorMenu = NULL;
        }
    }


    if (bRebuild)
    {
        lpqrmi->ModeMenu = GetModeMenu( iDisplay, bNeedtoSort );

        if (iMonitors==1)
        {
            MonitorMenu = lpqrmi->ModeMenu;
            AppendMainMenu();
        }
        else
        {
            //  If ModifyMenu replaces a menu item that opens a drop-down menu or submenu, the
            //  function destroys the old drop-down menu/submenu & frees the memory used by it.

            ModifyMenu( MonitorMenu, iDisplay, MF_BYPOSITION | MF_POPUP, (UINT_PTR)lpqrmi->ModeMenu,
                        (pMonitors[iDisplay].bPrimary ? pMonitors[iDisplay].PrimaryMonitorName : pMonitors[iDisplay].MonitorName) );
        }
    }
}


//
//********************************************************************
//
//   HandleFreqMenu( )
//
//   Either append submenu to res/bpp, save it for later, or
//   ditch it and put all Hz entries on mode menu.
//   If there is only one Hz for a given Res, we dont need it.
//
//********************************************************************
//
VOID HandleFreqMenu( INT iDisplay, int FreqCount, int ResCounter, int pFirst)
{

    PTCHAR Res=NULL;
    PTCHAR Hz=NULL;
    LPQRMONITORINFO lpqrmi;         //  temporary ptr


    lpqrmi = &pMonitors[iDisplay];
    GetModeName(&lpqrmi->pModes[pFirst].dm, &Res, &Hz);

    //
    //  Dont use submenus if there is only 1 Hz
    //  This is always true when freqmenulocation==IDD_ALLMODEMENU
    //  OR not showing frequency menus
    //  Concatenate Res & Hz into one string (IF fShowFreqs)
    //

    if ( FreqCount == 1 )
    {
        if (fShowFreqs)
        {
            PTCHAR ResHz;

            if (ResHz=LocalAlloc( LPTR, sizeof(TCHAR)*
                              (lstrlen(Res)+lstrlen(Hz)+1) ))
            {
                wsprintf(ResHz,TEXT("%s%s"),Res,Hz);
                AppendMenu(lpqrmi->ModeMenu, MF_STRING,
                           (iDisplay+1)*MENU_RES+pFirst, ResHz);
            }

            LocalFree(ResHz);
        }
        else
        {
            AppendMenu(lpqrmi->ModeMenu, MF_STRING,
                       (iDisplay+1)*MENU_RES+pFirst, Res);
        }
    }

    else
    {
        int i=0;
        int nAppended=0;

        //
        //  Create Popup and append all Hz strings
        //  Append FreqCount items, possibly skipping over some modes
        //

        lpqrmi->FreqMenu[ResCounter] = CreatePopupMenu();

        for (i=0; nAppended < FreqCount; i++)
        {

            PTCHAR LoopRes=NULL;
            PTCHAR LoopHz=NULL;

            //
            //  Skip untested modes if requested.  FreqCount does NOT
            //  include skipped modes, so we count up with nAppended, not i.
            //

            if ( !fShowTestedModes || fGoodMode(&lpqrmi->pModes[pFirst+i]) )
            {

                GetModeName(&lpqrmi->pModes[pFirst+i].dm,&LoopRes,&LoopHz);
                AppendMenu(lpqrmi->FreqMenu[ResCounter],MF_STRING,
                           (iDisplay+1)*MENU_RES+pFirst+i,LoopHz);
                nAppended++;

                LocalFree(LoopRes);
                LocalFree(LoopHz);
                LoopRes=NULL;
                LoopHz=NULL;
            }
        }


        //
        //  Hang menu off side of each bpp/res
        //

        if (FreqMenuLocation == IDD_SUBMENUS)
        {
            AppendMenu(lpqrmi->ModeMenu,MF_POPUP,
                       (UINT_PTR)lpqrmi->FreqMenu[ResCounter],Res);
        }

        else
        {
            //
            //  Only show submenu for the current mode
            //  Use BESTHZ mode or the VALID mode with the
            //  lowest frequency.
            //

            if ( (FreqMenuLocation == IDD_ONEMENUMOBILE) ||
                 (FreqMenuLocation == IDD_ONEMENUBOTTOM) )
            {

                int BestHz=0;
                int index;

                //
                //  Start with highest freq (pFirst+i-1)
                //  and work down to pFirst looking for BestHz.
                //  if we find BESTHZ use that one, else
                //  use last VALIDMODE we get before loop ends
                //

                for (index=pFirst+i-1 ; index >= pFirst; index--)
                {
                    if ( VALIDMODE(&lpqrmi->pModes[index]) == MODE_BESTHZ )
                    {
                        BestHz = index;
                        break;
                    }
                    else
                    {
                        if (VALIDMODE(&lpqrmi->pModes[index])!=MODE_INVALID)
                        {
                            BestHz = index;
                        }
                    }
                }

                //
                //  No valid/besthz modes.  Use smallest Hz for that Res
                //

                if (!BestHz)
                {
                    BestHz = pFirst;
                }

                AppendMenu(lpqrmi->ModeMenu,MF_STRING,
                           (iDisplay+1)*MENU_RES+BestHz,Res);
            }
        }
    }

    LocalFree(Res);
    LocalFree(Hz);

}


//
//********************************************************************
//
//   GetModeMenu( INT, BOOL )
//
//   Build the mode menu with each resolution/BPP having a
//   pointer to its own frequency submenu
//
//********************************************************************
//

HMENU GetModeMenu ( INT iDisplay, BOOL bNeedtoSort )
{

    int  n;                        // counter
    BOOL bMajorChange=FALSE;       // change in the major sort order field
    BOOL bMinorChange=FALSE;       // change in the minor sort order field
    int  FreqCount=0;             // number of freqs on the current submenu
    int  ResCounter=0;            // Res/Color defines the freqmenu #
    INT   FirstMode=-1;            // index in pmodes; 1st mode for given res/bpp
    LPQRMONITORINFO lpqrmi;        //  temporary ptr



    lpqrmi = &pMonitors[iDisplay];


    if (!lpqrmi->ModeMenu)
    {
        lpqrmi->ModeMenu = CreatePopupMenu();


        if (bNeedtoSort)
        {
            qsort( (void*)  lpqrmi->pModes,
                   (size_t) lpqrmi->iModes,
                   (size_t) sizeof(DEVMODEINFO),
                   ( int (_cdecl*)(const void*,const void*) ) CompareDevmodes );

            lpqrmi->pCurrentdm = NULL;
        }


        //
        // For each devmode, add res/color to menu.
        // Make a submenu of frequencies for each res/color
        //

        for (n=0; n < lpqrmi->iModes; n++)
        {
            LPDEVMODEINFO  pDM = &lpqrmi->pModes[n];

            //
            // Tested successfully or might require restart
            //

            if ( ( (CDSTEST(pDM) == DISP_CHANGE_SUCCESSFUL) ||
                   (fShowModesThatNeedRestart && (CDSTEST(pDM) == DISP_CHANGE_RESTART)) ) &&

                 ( !fShowTestedModes || fGoodMode(pDM) )     )
            {


                //
                //  Check for change in the major/minor sort item
                //  *only after we 'initialize' firstmode below
                //

                if (FirstMode == -1)
                {

                //
                //  First time thru, initialize FirstMode,counter
                //

                    FirstMode = n;
                    FreqCount=0;

                }

                else
                {
                    if( BPP(&lpqrmi->pModes[FirstMode].dm) != BPP(&pDM->dm) )
                    {
                        bMajorChange = fSortByBPP;
                        bMinorChange = !fSortByBPP;
                    }

                    if( ( XRES(&lpqrmi->pModes[FirstMode].dm) != XRES(&pDM->dm) ) ||
                        ( YRES(&lpqrmi->pModes[FirstMode].dm) != YRES(&pDM->dm) ) )
                    {
                        bMajorChange |= !fSortByBPP;
                        bMinorChange |= fSortByBPP;
                    }


                    //
                    //  The BPP and/or the Resolution changed.
                    //

                    if ( bMajorChange || bMinorChange )
                    {

                        //
                        //  Appends a Res/BPP and a submenu if applicable
                        //

                        HandleFreqMenu(iDisplay,FreqCount,ResCounter,FirstMode);
                        ResCounter++;

                        //
                        //  Need a separator when major sort item changes
                        //

                        if ( bMajorChange )
                        {
                            AppendMenu(lpqrmi->ModeMenu,MF_SEPARATOR,0,NULL);
                            ResCounter++;
                        }


                        //
                        // n is first mode for the new res/bpp
                        // reset counter, flags
                        //

                        FirstMode  = n;
                        FreqCount= 0;
                        bMajorChange = FALSE;
                        bMinorChange = FALSE;
                    }
                }


                //
                //  Fill in fields for this mode; inc freqcount
                //


                MENUITEM( pDM ) = (iDisplay+1)*MENU_RES+n;
                FREQMENU( pDM ) = ResCounter;
                FreqCount++;


                //
                //  ALLMODEMENU - Force menu append every time
                //

                if (FreqMenuLocation == IDD_ALLMODEMENU)
                {
                   bMinorChange = TRUE;
                }


            }

        }  // end for


        //
        //  NO VALID MODES!!!  Certainly the current mode should be valid.  Make
        //  this mode VALID. Setup FreqCount, FirstMode for the last HandleFreqMenu
        //

        if (FirstMode == -1)
        {
            DEVMODEINFO DisplayModeInfo;

            DisplayModeInfo.dm.dmSize= sizeof(DEVMODE);
            GetCurrentDevMode(iDisplay, &DisplayModeInfo.dm);

            for (n=0;
                 CompareDevmodes(&DisplayModeInfo,&lpqrmi->pModes[n]) != 0;
                 n++ )
            {
            }

            VALIDMODE(&lpqrmi->pModes[n]) = MODE_BESTHZ;
            FirstMode = n;
            FreqCount = 1;

        }


        //
        //  Handle the FreqMenu for the last Res/BPP.
        //

        HandleFreqMenu(iDisplay,FreqCount,ResCounter,FirstMode);


        //
        //  Update menu checks; mode status
        //

        CheckMenuItemCurrentMode( iDisplay );


        //
        //  Put Hz menu next to current mode, or at the bottom
        //

        if (FreqMenuLocation == IDD_ONEMENUMOBILE)
        {
            MENUITEMINFO mii;

            ZeroMemory(&mii, sizeof(mii));
            mii.cbSize = sizeof(mii);
            mii.fMask = MIIM_SUBMENU;
            mii.hSubMenu = lpqrmi->FreqMenu[FREQMENU(lpqrmi->pCurrentdm)];
            SetMenuItemInfo(lpqrmi->ModeMenu, FREQMENU(lpqrmi->pCurrentdm), MF_BYPOSITION, &mii);
        }

        else
        {

            if (FreqMenuLocation == IDD_ONEMENUBOTTOM)
            {
                PTCHAR szRefRate;
                UINT flags=MF_POPUP;

                szRefRate = GetResourceString(IDS_REFRESHRATE);

                if ( !lpqrmi->FreqMenu[FREQMENU(lpqrmi->pCurrentdm)] )
                {
                    flags = MF_GRAYED;
                }

                AppendMenu(lpqrmi->ModeMenu,MF_SEPARATOR,0,NULL);
                AppendMenu(lpqrmi->ModeMenu, flags,
                           (UINT_PTR)lpqrmi->FreqMenu[FREQMENU(lpqrmi->pCurrentdm)],
                           szRefRate);

                LocalFree(szRefRate);
            }
        }
    }

    return (lpqrmi->ModeMenu);
}


//
//********************************************************************
//
//   AppendMainMenu( VOID )
//
//   Append main menu (from .rc file) to monitor menu
//
//********************************************************************
//

VOID AppendMainMenu()
{

#ifdef MAINWITHMODE

    int  n;                        // counter

    //
    //  Add main menu to bottom of mode menu.  These menu
    //  items come from MainMenu as defined in .rc file
    //

    AppendMenu(MonitorMenu,MF_SEPARATOR,0,NULL);

    for (n=0; n < GetMenuItemCount(MainMenu); n++)
    {

        MENUITEMINFO mii;

        //
        //  Set up mii struct to retrieve the length of
        //  each menu item string via GetMenuItemInfo().
        //

        ZeroMemory(&mii, sizeof(mii));
        mii.cbSize = sizeof(mii);
        mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID;

        mii.cch = GetMenuString(MainMenu, n, NULL, 0, MF_BYPOSITION) +1;

        //
        //  Allocate enough memory and read in the string.
        //

        if (mii.dwTypeData = LocalAlloc( LPTR, mii.cch*sizeof(TCHAR) ))
        {

            //
            //  Read in the string, get it's ID and append to the menu
            //

            if (GetMenuString(MainMenu, n, mii.dwTypeData, mii.cch,MF_BYPOSITION))
            {
                mii.wID=GetMenuItemID(MainMenu, n);

                AppendMenu(MonitorMenu, MF_STRING, mii.wID, mii.dwTypeData);
            }

            LocalFree(mii.dwTypeData);
        }
    }

    SetMenuDefaultItem(MonitorMenu,MENU_PROPERTIES,MF_BYCOMMAND);

#endif

}


//
//********************************************************************
//
//   GetMonitorMenu( BOOL )
//
//   Build all mode menus with each resolution/BPP having a
//   pointer to its own frequency submenu
//
//********************************************************************
//

HMENU GetMonitorMenu ( BOOL bNeedtoSort )
{


    if (!MonitorMenu)
    {
        //
        //  Use Modemenu of iDisplay==0 as the monitor menu
        //

        if (iMonitors == 1)
        {
            MonitorMenu = GetModeMenu(0, bNeedtoSort);
        }
        else
        {
            INT    iDisplay;

            MonitorMenu = CreatePopupMenu();

            for (iDisplay=0; iDisplay < iMonitors; iDisplay++)
            {
                //
                //  append each monitor name to the main monitor menu
                //

                AppendMenu( MonitorMenu, MF_POPUP,
                            (UINT_PTR)GetModeMenu(iDisplay, bNeedtoSort),
                            (pMonitors[iDisplay].bPrimary ? pMonitors[iDisplay].PrimaryMonitorName : pMonitors[iDisplay].MonitorName) );
            }

        }

        AppendMainMenu();

    }

    return MonitorMenu;
}



//
//********************************************************************
//
//   SetMonitorDeviceInfo( BOOL bFirstTime )
//
//   Set monitor info fields : primary?  attached?
//   and the correct monitor name, based on bPrimary
//
//********************************************************************
//
BOOL SetMonitorDeviceInfo( BOOL bFirstTime )
{
    BOOL    bFoundPrimary=FALSE;
    BOOL    bChange=FALSE;
    PTCHAR  szMonitorRes;
    int     iDisplay;
    int     n;
    DISPLAY_DEVICE DispDev;



    if ( (iMonitors > 1) && (lpfnEDD) )
    {

        szMonitorRes = GetResourceString(IDS_MONITOR);

        DispDev.cb = sizeof(DispDev);

        iDisplay=0;

        for ( n=0; (lpfnEDD)(NULL, n, &DispDev, 0); n++ )
        {

            if ( !(DispDev.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) )
            {

                DWORD dwSize;
                TCHAR index[8];

                //
                //  For each display, get the monitor name, primary monitor name, & Device name
                //  Alloc enough memory for MonitorName string to have up to 3 digits for the monitor index.
                //

                if (DispDev.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
                {
                    bChange |= (pMonitors[iDisplay].bPrimary != TRUE);
                    pMonitors[iDisplay].bPrimary = TRUE;
                    bFoundPrimary=TRUE;
                }
                else
                {
                    bChange |= (pMonitors[iDisplay].bPrimary != FALSE);
                    pMonitors[iDisplay].bPrimary = FALSE;
                }

                //
                //  Allocation sizes, device name, and primarymonitorname all never change
                //

                if (bFirstTime)
                {
                    pMonitors[iDisplay].DeviceName  = GlobalAlloc(GPTR, sizeof(TCHAR)*(lstrlen(DispDev.DeviceName)+1));
                    pMonitors[iDisplay].MonitorName = GlobalAlloc( GPTR, sizeof(TCHAR)*dwSize );
                    pMonitors[iDisplay].PrimaryMonitorName = GlobalAlloc( GPTR, sizeof(TCHAR)*dwSize );
                }

                // Memory allocation failed we can't continue
                if (!pMonitors[iDisplay].DeviceName || 
                    !pMonitors[iDisplay].MonitorName || 
                    !pMonitors[iDisplay].PrimaryMonitorName)
                    return FALSE;

                if (bFirstTime)
                {
                    lstrcpy(pMonitors[iDisplay].DeviceName, DispDev.DeviceName);

                    dwSize = lstrlen(DispDev.DeviceString) + lstrlen(szMonitorRes);
                    dwSize += lstrlen(TEXT("Primary"));

                    wsprintf( pMonitors[iDisplay].PrimaryMonitorName, szMonitorRes,
                                  TEXT("Primary "), TEXT(""), DispDev.DeviceString );

                    bChange = TRUE;
                }


                //  this ensures we always have primary, 2,3,4, etc. (never a monitor 0 or 1)
                //

                _itot( (iDisplay + (bFoundPrimary ? 1 : 2)),index,8);
                lstrcat(index,TEXT(" "));

                wsprintf( pMonitors[iDisplay].MonitorName, szMonitorRes,
                          TEXT(""), index, DispDev.DeviceString);


                bChange |= (pMonitors[iDisplay].bAttached != (BOOL)(DispDev.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP));
                pMonitors[iDisplay].bAttached = (DispDev.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP);

                iDisplay++;
            }

            DispDev.cb = sizeof(DispDev);   // always reset before next call to be safe
        }

        LocalFree(szMonitorRes);

        if (!bFirstTime)
        {
            for (n=0; n< iMonitors; n++)
            {
                ModifyMenu( MonitorMenu, n, MF_BYPOSITION | MF_POPUP, (UINT_PTR)pMonitors[n].ModeMenu,
                           (pMonitors[n].bPrimary ? pMonitors[n].PrimaryMonitorName : pMonitors[n].MonitorName));
            }
        }
    }

    return bChange;
}



//
//********************************************************************
//
//   BuildMonitorArray( )
//
//   Allocate & fill in a monitorinfo struct for each display device
//
//********************************************************************
//

BOOL BuildMonitorArray( )
{

    int            iDisplay;
    DISPLAY_DEVICE DispDev;



    //
    // Find the number of monitors/displaydevices
    // alloc a monitorinfo struct per monitor
    //

    iMonitors = 1;
    //    getSysMet != EnumDispDevices!!!  (netmtg, etc.)
    //    iMonitors = max(GetSystemMetrics(SM_CMONITORS),1);


    //
    //  EDSEx is win98 & NT5 only -- the ones with multimonitor, the check for EDD is just to
    //  check that we have the api we're going to call.  win95 osr2.5/NT4 are single-mon only
    //

    if (lpfnEDSEx && lpfnEDD)
    {
        DispDev.cb = sizeof(DispDev);

        iMonitors=0;
        for (iDisplay=0; (lpfnEDD)(NULL, iDisplay, &DispDev, 0); iDisplay++)
        {
            if ( !(DispDev.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) )
            {
                iMonitors++;
            }
        }
    }

    pMonitors = GlobalAlloc(GPTR, iMonitors*sizeof(QRMONITORINFO));


    if (pMonitors)
    {
        //
        //  On a multimon system, get the display device info --
        //     monitor and device names + primary?  and attached?
        //

        if ( (iMonitors > 1) && (lpfnEDD) )
        {
            SetMonitorDeviceInfo( TRUE );
        }
        else
        {
            pMonitors[0].DeviceName  = NULL;
            pMonitors[0].MonitorName = NULL;
            pMonitors[0].PrimaryMonitorName = NULL;
        }
    }
    else
    {
        iMonitors = 0;
    }

    return pMonitors != NULL;
}



//
//********************************************************************
//
//   BuildDevmodeLists( )
//
//   Enumerate all devmodes for each display device into an array.
//   Sort them, remove duplicates, and filter out 4bpp modes
//   Create a popup menu for each display device (put all modes
//   on the main menu if it is a single monitor machine)
//
//********************************************************************
//

BOOL BuildDevmodeLists( )
{

    DEVMODE   DisplayMode;      // temporary devmode storage
    BOOL      bShrink=FALSE;    // set if iModes ever decreases
    int       nModes,
              n,
              iDisplay;         // counters

    LPDEVMODEINFO    lpdm;
    LPQRMONITORINFO  lpqrmi;



    DisplayMode.dmSize= sizeof(DEVMODE);

    //
    //   Fill in each display's/monitor's mode list
    //

    for (iDisplay=0; iDisplay < iMonitors; iDisplay++)
    {
        DWORD dwFlags = 0;

        lpqrmi = &pMonitors[iDisplay];

        lpqrmi->ModeMenu = NULL;
        lpqrmi->FreqMenu = NULL;
        lpqrmi->iModes = 0;
        lpqrmi->pModes = NULL;
        lpqrmi->pCurrentdm = NULL;


        //
        // Find the number of modes known by driver for each monitor
        //

        if (lpfnEDSEx)
        {
            for( nModes=0; (lpfnEDSEx)(pMonitors[iDisplay].DeviceName, nModes, &DisplayMode, dwFlags); nModes++)
                ;
        }
        else
        {
            for( nModes=0; EnumDisplaySettings(pMonitors[iDisplay].DeviceName, nModes, &DisplayMode); nModes++)
                ;
        }

        //
        // Get space for all modes
        //

        lpqrmi->pModes = (LPDEVMODEINFO) GlobalAlloc( GPTR, nModes*sizeof(DEVMODEINFO) );
        lpdm = lpqrmi->pModes;

        if( !lpdm )
        {
            DestroyModeMenu( iDisplay, FALSE, FALSE );
            return FALSE;
        }


        //
        //  Get all display modes into the pModes array
        //

        for( n=0; n<nModes; n++ )
        {
            lpdm[n].dm.dmSize= sizeof(DEVMODE);

            //
            // Get next mode into next spot in pModes
            //

            if (lpfnEDSEx)
            {
                (lpfnEDSEx)(pMonitors[iDisplay].DeviceName, n, &lpdm[n].dm, dwFlags );
            }
            else
            {
                EnumDisplaySettings(pMonitors[iDisplay].DeviceName, n, &lpdm[n].dm );
            }


            //
            //  If any Hz is NOT 0 or 1 (default), then turn on Freq flag.
            //  This will be true on NT.  Win95 will always return 0 or 1.
            //

            if ( HZ(&lpdm[n].dm)  &&  (HZ(&lpdm[n].dm) != 1) )
                QuickResFlags |= QF_SHOWFREQS;
        }


        //
        // sort them according to QF_SORTBYBPP :
        //  (1) BPP X Y HZ  or   (2) X Y BPP HZ
        //

        qsort( (void*)  lpdm,
               (size_t) nModes,
               (size_t) sizeof(DEVMODEINFO),
               ( int (_cdecl*)(const void*,const void*) ) CompareDevmodes );


        //
        //   Filter out any duplicate devmodes return by the driver
        //   and any modes with x resolution < 640 pixels.  We dont
        //   want to show ModeX modes (320x200, 320x240, etc.)
        //

        if (nModes > 1 )
        {

            for (n=0; n+1 < nModes; )
            {

                if (XRES(&lpdm[n].dm) < 640)
                {
                    nModes--;
                    bShrink = TRUE;
                    MoveMemory( &lpdm[n],
                                &lpdm[n+1],
                                (nModes-n)*sizeof(DEVMODEINFO) );
                }
                else
                {
                    //
                    //  If consecutive devmodes are identical, then copy the next
                    //  one over the dup and decrement iModes (# of devmodes).
                    //

                    while ( CompareDevmodes(&lpdm[n],&lpdm[n+1]) == 0 )
                    {
                        //
                        //  Don't go past the last devmode
                        //

                        if (n+2 < nModes--)
                        {
                            bShrink = TRUE;
                            MoveMemory( &lpdm[n],
                                        &lpdm[n+1],
                                        (nModes-n)*sizeof(DEVMODEINFO) );
                        }
                        else
                        {
                            break;
                        }
                    }

                    n++;
                }
            }
        }


        //
        // Check CDS return value for all modes and eliminate all 4bpp
        // modes that have a corresponding 8bpp mode at the same res
        //

        for (n=0; n < nModes; n++)
        {

            CDSTEST(&lpdm[n]) = (WORD)ChangeDisplaySettingsEx( lpqrmi->DeviceName, &lpdm[n].dm,
                                                                    NULL, CDS_TEST, 0);

            //
            //  Filter out all 4BPP modes that have an 8BPP mode at the same resolution
            //

            if (BPP(&lpdm[n].dm)==8)
            {
                INT i;

                for (i=0; i < n; )
                {

                    if ( (BPP (&lpdm[i].dm) == 4)    &&
                         (XRES(&lpdm[n].dm) == XRES(&lpdm[i].dm)) &&
                         (YRES(&lpdm[n].dm) == YRES(&lpdm[i].dm))    )
                    {
                        nModes--;
                        bShrink = TRUE;
                        MoveMemory( &lpdm[i],
                                    &lpdm[i+1],
                                    (nModes-i)*sizeof(DEVMODEINFO) );
                        n--;
                    }
                    else
                    {
                        i++;
                    }
                }
            }
        }

        //
        //  nModes might have decreased; might as well free up some memory.
        //  Note that iModes could NOT have increased, so the ReAlloc will be okay.
        //

        if (bShrink)
        {
            lpqrmi->pModes = (LPDEVMODEINFO) GlobalReAlloc(lpqrmi->pModes,
                                                           nModes*sizeof(DEVMODEINFO),
                                                           GMEM_MOVEABLE );
        }

        lpqrmi->iModes = nModes;

        //
        //  At most, we need 1 freqmenu per mode (actually it's always < #modes.)
        //  Note : separators take up 1 (unused) hmenu in the array, so it would
        //  that we need hmenus > #modes, when "all modes on main menu".  But,
        //  in that case, we dont use the freq submenus at all. :)
        //

        lpqrmi->FreqMenu = (HMENU*) GlobalAlloc(GPTR,nModes*sizeof(HMENU));
        for (n=0; n < nModes; n++)
        {
            lpqrmi->FreqMenu[n] = NULL;
        }


        //
        //  Get modeflags from registry or zero out modeflags[]
        //

        GetDevmodeFlags(iDisplay);


        //
        //  Call GetModeMenu to put all strings/popups in place
        //  Current mode will be the best until user changes it.
        //

        GetModeMenu( iDisplay, FALSE );

        VALIDMODE(lpqrmi->pCurrentdm) = MODE_BESTHZ;

    }

    return TRUE;
}


//
//********************************************************************
//
//   DestroyDevmodeLists( )
//
//   free all the memory allocated for modes and menus for each device
//
//********************************************************************
//

BOOL DestroyDevmodeLists()
{

    int              iDisplay;
    LPQRMONITORINFO  lpqrmi;



    for (iDisplay=0; iDisplay < iMonitors; iDisplay++)
    {

        lpqrmi = &pMonitors[iDisplay];

        //
        //  DestroyModeMenu has freed all the individual menus in this array for us
        //

        if (lpqrmi->FreqMenu)
        {
            GlobalFree(lpqrmi->FreqMenu);
            lpqrmi->FreqMenu = NULL;
        }

        if (lpqrmi->pModes)
        {
            GlobalFree(lpqrmi->pModes);
            lpqrmi->pModes = NULL;
        }

        lpqrmi->iModes = 0;
        lpqrmi->pCurrentdm = NULL;

    }

    return TRUE;
}



//
//********************************************************************
//
//   DoProperties( )
//
//   Calls the control panel applet to show 'Display Properties'
//   specifically the display settings
//
//********************************************************************
//

void DoProperties( )
{
    STARTUPINFO          si;
    PROCESS_INFORMATION  pi;
    TCHAR lpszProperties[64] = DISPLAYPROPERTIES;

    GetStartupInfo( &si );


    //
    // Start it up.
    //

    if (CreateProcess(NULL, lpszProperties, NULL, NULL, FALSE,
                      0,    NULL,           NULL, &si,  &pi))
    {


        //
        //  Dont care what wait return value is, but we want
        //  to 'disable' tray icon for a minute or until the
        //  user kills desk.cpl
        //

        WaitForSingleObject( pi.hProcess, 60*1000 );


        CloseHandle ( pi.hThread );
        CloseHandle ( pi.hProcess );
    }
}


//
//********************************************************************
//
//   AppWndProc(HWND, UINT, WPARAM, LPARAM)
//
//   Main window proc to process messages
//
//********************************************************************
//

LRESULT CALLBACK AppWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    POINT pt;                  // Get cursor pos for the menu placement
    INT   i;

    switch (msg)
    {

        case WM_CREATE:

            //
            //   Add icon to tray next to time
            //

            TrayMessage(hwnd, NIM_ADD, TRAY_ID, AppIcon);

            break;


        case WM_DESTROY:

            //
            //   Remove icon from tray.
            //

            TrayMessage(hwnd, NIM_DELETE, TRAY_ID, NULL );

            PostQuitMessage(0);

            break;


        case WM_DISPLAYCHANGE:

            //
            //  New settings.  Reset pCurrentdm as index in pModes
            //  No need to destroy/rebuild the mode menu, but bPrimary,
            //  bAttached may have changed.
            //
            //  The Waiting flag makes this a no-op, when its a qres-initiated change
            //

            if (!Waiting)
            {
                for (i=0; i<iMonitors; i++)
                {
                    pMonitors[i].pCurrentdm = NULL;
                    CheckMenuItemCurrentMode(i);
                }

                SetMonitorDeviceInfo( FALSE );
            }

            break;


#if 0
hard to understand when and why we get this message.  better leave it alone
        case WM_DEVICECHANGE:

            if (wParam == DBT_CONFIGCHANGED ||
                wParam == DBT_MONITORCHANGE)
            {
                for (i=0; i<iMonitors; i++)
                {
                    DestroyModeMenu( i, FALSE, FALSE );
                    SetDevmodeFlags( i, TRUE );
                }

                if (MonitorMenu)
                {
                    DestroyMenu(MonitorMenu);
                    MonitorMenu = NULL;
                }
                DestroyDevmodeLists();
                BuildDevmodeLists();
                MonitorMenu = GetMonitorMenu( TRUE );
            }
            break;
#endif


        case WM_COMMAND:
        {

            switch (LOWORD(wParam))
            {

                case MENU_CLOSE:

                    PostMessage(hwnd, WM_CLOSE, 0, 0);

                    break;

                case MENU_PROPERTIES:

                    //
                    // Start control panel applet
                    //

                    DoProperties();

                    break;


                case MENU_ABOUT:

                    //
                    // Show a generic about box
                    //

                    MsgBox(IDS_ABOUT, 0, MB_OK );

                    break;


                case MENU_OPTIONS:

                    //
                    // After showing options dlg box, show mode menu again
                    //

                    if (fShowFreqs)
                        DialogBox(hInstApp, MAKEINTRESOURCE(NTOptions), NULL, NTOptionsDlgProc);
                    else
                        DialogBox(hInstApp, MAKEINTRESOURCE(W95Options),NULL, W95OptionsDlgProc);

                    SetTimer(hwnd, TRAY_ID, 10, NULL);

                    break;


                default:
                {

                    //
                    // Change devmode to pModes[OffsetPdev]
                    //

                    INT OffsetPdev;
                    INT iDisplay;

                    //
                    // The menu item is an offset from MENU_RES
                    // of the selected item.
                    //

                    iDisplay   = LOWORD(wParam) / MENU_RES - 1;
                    OffsetPdev = LOWORD(wParam) % MENU_RES;

                    //
                    // Check that the offset is within range
                    //

                    if( OffsetPdev >= 0 && OffsetPdev < pMonitors[iDisplay].iModes )
                    {

                        //
                        // if different from current devmode then change it
                        //

                        if ( CompareDevmodes( &pMonitors[iDisplay].pModes[OffsetPdev],
                                               pMonitors[iDisplay].pCurrentdm) )
                        {
                            SetMode(hwnd, iDisplay, OffsetPdev);
                        }

                    }

                }

                break;

            }

            break;

        }


        case WM_TIMER:

            //
            // Left click was not a double-click
            //

            KillTimer(hwnd, TRAY_ID);
            GetCursorPos(&pt);
            SetForegroundWindow(hwnd);

            //
            // Create and/or Get resolutions menu
            //

            TrackPopupMenu(GetMonitorMenu( FALSE ), TPM_LEFTBUTTON,
                           pt.x, pt.y, 0, hwnd, NULL);

            break;


        case TRAY_MSG:
        {

            //
            // No messages processed while waiting on
            // a dlg/msg box to return
            //

            if (!Waiting)
            {

                switch (lParam)
                {
                    case WM_RBUTTONUP:

                        //
                        // Properties, about, Exit
                        //

                        SetForegroundWindow(hwnd);
                        GetCursorPos(&pt);

                        TrackPopupMenu(MainMenu, TPM_RIGHTBUTTON,
                                       pt.x, pt.y, 0, hwnd, NULL);

                        break;


                    case WM_LBUTTONDOWN:

                        //
                        // Resolutions menu
                        //

                        SetTimer(hwnd, TRAY_ID, GetDoubleClickTime()+10, NULL);

                        break;



                    case WM_LBUTTONDBLCLK:

                        //
                        // start control panel applet
                        //

                        KillTimer(hwnd, TRAY_ID);
                        DoProperties();

                        break;
                }

            }

        }

        break;

    }

    return DefWindowProc(hwnd,msg,wParam,lParam);

}


//
//********************************************************************
//
//  MsgBox(int, UINT, UINT)
//
//  Generic messagebox function that can print a value into
//  a format string
//
//********************************************************************
//

int MsgBox(int id, UINT value, UINT flags)
{

    PTCHAR msgboxtext=NULL;           // message box body text
    INT  ret = 0;
    MSGBOXPARAMS mb;


    //
    //  Ignore tray clicks while msgbox is up, and
    //  Show at least an OK button.
    //

    Waiting = TRUE;
    if (flags == 0)
    {
        flags = MB_OK | MB_USERICON;
    }


    //
    //  Can print a value into a format string, if value!=0.
    //

    if (value)
    {
        PTCHAR msgboxfmt;                // body test format

        if (msgboxfmt = GetResourceString ( id ))
        {
            if (msgboxtext = LocalAlloc ( LPTR, sizeof(TCHAR)*
                             (lstrlen(msgboxfmt)+INT_FORMAT_TO_5_DIGITS+1)))
            {
                wsprintf(msgboxtext,msgboxfmt,value);
            }

            LocalFree( msgboxfmt );
        }
    }

    else
    {
       msgboxtext = GetResourceString ( id );
    }


    if (msgboxtext)
    {

        mb.cbSize               = sizeof(mb);
        mb.hwndOwner            = NULL;
        mb.hInstance            = hInstApp;
        mb.lpszText             = msgboxtext;
        mb.lpszCaption          = szAppName;
        mb.dwStyle              = flags;
        mb.lpszIcon             = szAppName;
        mb.dwContextHelpId      = 0;
        mb.lpfnMsgBoxCallback   = NULL;
        mb.dwLanguageId         = MAKELANGID (LANG_NEUTRAL, SUBLANG_NEUTRAL);;


        //
        //  Special API for the about box. otherwise, use Messageboxindirect
        //

        if (id == IDS_ABOUT)
        {
            ret = ShellAbout(mb.hwndOwner, mb.lpszCaption, mb.lpszText, AppIcon);
        }

        else
        {

            if (flags & MB_USERICON)
            {
                //
                //  only use MessageBoxIndirect if we have to.
                //  has problems on win9x.
                //

                ret = MessageBoxIndirect(&mb);
            }

            else
            {
                //
                //  MessageBoxEx works great on both NT and Win95
                //

                ret = MessageBoxEx ( mb.hwndOwner, mb.lpszText, mb.lpszCaption,
                                     mb.dwStyle,   (WORD)mb.dwLanguageId );
            }
        }

        //
        //  Free string memory; start processing tray msgs again
        //

        LocalFree( msgboxtext );
    }

    Waiting = FALSE;

    return ret;

}


//
//********************************************************************
//
//  WinMain
//
//********************************************************************
//

int NEAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
{
    WNDCLASS  cls;
    MSG       msg;
    HWND      hwnd;
    INT       iDisplay;
    HINSTANCE hInstUser;

    hInstApp = hInst;
    szAppName = GetResourceString( IDS_TITLE );


    //
    //   App is already running.  Do not start a 2nd instance
    //

    if ( FindWindow( szAppName, szAppName ) )
    {
        return 0;
    }

    if (hInstUser=GetModuleHandle(TEXT("user32.dll")))
    {
        lpfnEDD =   GetProcAddress( hInstUser, ENUMDISPLAYDEVICES    );
        lpfnEDSEx = GetProcAddress( hInstUser, ENUMDISPLAYSETTINGSEX );
    }


    AppIcon = LoadIcon(hInst,szAppName);


    //
    //  Register a class for the main application window
    //

    cls.lpszClassName  = szAppName;
    cls.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
    cls.hInstance      = hInstApp;
    cls.hIcon          = AppIcon;
    cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
    cls.lpszMenuName   = szAppName;
    cls.style          = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
    cls.lpfnWndProc    = AppWndProc;
    cls.cbWndExtra     = 0;
    cls.cbClsExtra     = 0;

    if (!RegisterClass(&cls))
        return FALSE;

    hwnd = CreateWindow(szAppName,
                        szAppName,
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
                        NULL, NULL,
                        hInstApp, NULL);


    //
    //  Properties, about, exit - properties is the default
    //

    MainMenu = GetSubMenu(GetMenu(hwnd), 0);
    SetMenuDefaultItem(MainMenu,MENU_PROPERTIES,MF_BYCOMMAND);


    //
    //  Get flags from registry and build the modemenu
    //  from scratch.
    //

    GetQuickResFlags( );

    if (!BuildMonitorArray())
    {
        return FALSE;
    }

    if (!BuildDevmodeLists())
    {
        return FALSE;
    }


    //
    // Update tray tooltip to be current resolution
    //

    TrayMessage( hwnd, NIM_MODIFY, TRAY_ID, AppIcon );


    //
    // Polling messages from event queue
    //

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }


    //
    //  write flags to registry
    //

    SaveAllSettings();


    //
    //  Free up dynamically allocated globals.
    //

    LocalFree ( szAppName );

    for (iDisplay=0; iDisplay<iMonitors; iDisplay++)
    {
        if (pMonitors[iDisplay].DeviceName)
            GlobalFree(pMonitors[iDisplay].DeviceName);

        if (pMonitors[iDisplay].MonitorName)
            GlobalFree(pMonitors[iDisplay].MonitorName);

        if (pMonitors[iDisplay].PrimaryMonitorName)
            GlobalFree(pMonitors[iDisplay].PrimaryMonitorName);

        GlobalFree(pMonitors[iDisplay].pModes);

        GlobalFree(pMonitors[iDisplay].FreqMenu);
    }

    GlobalFree(pMonitors);


    return (int)msg.wParam;
}


//
//********************************************************************
//
//   TrayMessage (HWND, DWORD, UINT, HICON )
//
//   Add/remove icon to/from tray next to the time
//
//********************************************************************
//

BOOL TrayMessage(HWND hwnd, DWORD msg, UINT id, HICON hIcon )
{

    NOTIFYICONDATA tnd;
    PTCHAR Res=NULL;
    PTCHAR Hz=NULL;
    UINT   uDisplay=0;
    UINT   uNewlen=0;

    tnd.cbSize           = sizeof(NOTIFYICONDATA);
    tnd.hWnd             = hwnd;
    tnd.uID              = id;
    tnd.szTip[0]         = '\0';
    tnd.uFlags           = NIF_MESSAGE|NIF_ICON|NIF_TIP;
    tnd.uCallbackMessage = TRAY_MSG;
    tnd.hIcon            = hIcon;


    //
    //  Changing tooltip text to match current resolution
    //  (Make sure pCurrentdm is valid / not NULL.)
    //

    if (msg == NIM_MODIFY)
    {

        do
        {

            if (pMonitors[uDisplay].pCurrentdm)
            {
                GetModeName(&(pMonitors[uDisplay].pCurrentdm->dm), &Res, &Hz);

                //
                //  calculate how long the string will be (need to be sure it's < 64)
                //  old tip + new Res + Hz (if applicable) + ", " (if its not the 1st mon)
                //

                uNewlen = lstrlen(tnd.szTip);

                if (Res)
                {
                    uNewlen += lstrlen(Res);
                }

                if (uDisplay > 0)
                {
                   uNewlen += 2;
                }

                if (fShowFreqs && Hz)
                {
                   uNewlen += lstrlen(Hz);
                }


                if (uNewlen < 64)
                {
                    //
                    //  this displays information will fit in the tooltip
                    //  add ", " if not 1st mon, then the Res, then Hz (if applicable)
                    //

                    if ( uDisplay > 0 )
                    {
                        lstrcat(tnd.szTip,TEXT(", "));
                    }

                    if (Res)
                    {
                        lstrcat(tnd.szTip,Res);
                    }

                    if (fShowFreqs && Hz)
                    {
                        lstrcat(tnd.szTip,Hz);
                    }
                }

                if (Res)
                {
                    LocalFree(Res);
                }

                if (Hz)
                {
                    LocalFree(Hz);
                }

                ++uDisplay;
            }

      }  while (uDisplay < (UINT)iMonitors);

    }

    //
    //  Adding the tray icon - Current devmode
    //  is not known so use AppName as tip
    //

    else
    {
        wsprintf(tnd.szTip, szAppName);
    }

    return Shell_NotifyIcon( msg, &tnd );
}



//
//*****************************************************************************
//
//  KeepNewResDlgProc(HWND, UINT, WPARAM, LPARAM )
//
//  User must enter Yes to keep new res, or we default back to the old res.
//
//*****************************************************************************
//

INT_PTR FAR PASCAL KeepNewResDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{

    //
    //  Save strings as static pointers, and free them only in YES/NO/ABORT/CANCEL,
    //  because they will otherwise disappear from a Win95 dialog box immediately
    //  after they are free'd.
    //

    static int     NOTimeOut;                  // countdown to 0
    static PTCHAR  NewResString=NULL;          // user friendly name for devmode
    static PTCHAR  NewHzString=NULL;           // and frequency
    static PTCHAR  szAt=NULL;                  // ", at"
    static PTCHAR  TotalString=NULL;           // "<wid x ht>, at <freq>"


    switch (message)
    {

       case WM_INITDIALOG:     // initialize values and focus

       {

            //
            //  Initialize values and focus
            //

            DEVMODE dm;


            //
            //  Ignore tray messages while waiting for yes/no.
            //  Wait KEEP_RES_TIMEOUT seconds.
            //

            Waiting=TRUE;


            //
            // Get current devmode; lparam is the iDisplay
            //
            GetCurrentDevMode( (INT)lParam, &dm );


            //
            // Get user friendly strings (concatenate Res & Hz, if applicable)
            //

            GetModeName( &dm, &NewResString, &NewHzString);

            if (NewResString)
            {
                if (fShowFreqs && NewHzString)
                {
                    szAt = GetResourceString ( IDS_AT );
                    
                    //
                    // Replace 2nd text item of msgbox
                    //

                    if (TotalString = LocalAlloc ( LPTR, sizeof(TCHAR)*
                                                 ( lstrlen(NewResString)+
                                                   lstrlen(NewHzString)+
                                                   lstrlen(szAt)+
                                                   1 ) ))
                    {
                        lstrcpy(TotalString, NewResString);
                        lstrcat(TotalString, szAt);
                        lstrcat(TotalString, NewHzString);

                        SetDlgItemText(hDlg, IDTEXT2, TotalString);
                    }
                }
                else
                {
                    SetDlgItemText(hDlg, IDTEXT2, NewResString);
                }
            }

            //
            //  Set timeout length and start waiting
            //

            NOTimeOut=KEEP_RES_TIMEOUT;

            SetTimer(hDlg,IDD_COUNTDOWN,1000,NULL);

            return (TRUE);

            break;

        }


        case WM_TIMER:

            {
                PTCHAR NoTextFmt=NULL;           // "NO: %d"
                PTCHAR NoText=NULL;              // e.g. "NO: 15"

                //
                // Still counting down
                //

                if ( NOTimeOut >= 0 )
                {
                    //
                    // Get format string for NO Button.
                    // Write it to NoText String and to dlg box
                    //

                    NoTextFmt = GetResourceString ( IDS_NOTEXT );

                    if (NoTextFmt)
                    {
                        NoText = LocalAlloc ( LPTR, sizeof(TCHAR)*
                                                    ( lstrlen(NoTextFmt)+1 ) );
                        wsprintf(NoText, NoTextFmt, NOTimeOut--);

                        SetDlgItemText(hDlg, IDNO, NoText);

                        LocalFree ( NoTextFmt );
                        LocalFree ( NoText );
                    }

                }

                else
                {
                    //
                    // Give up on the user - return NO
                    //

                    KillTimer(hDlg, IDD_COUNTDOWN);
                    SendMessage(hDlg, WM_COMMAND, IDNO, 0);
                }

                return (TRUE);

            }

            break;


        case WM_COMMAND:

            //
            // Start processing tray messages again
            //

            Waiting=FALSE;

            switch (LOWORD(wParam))

            {

                //
                //  return value based on the button pressed
                //

                case IDYES :
                case IDNO :
                case IDABORT :
                case IDCANCEL :

                    //
                    //  LocalFree handles NULL pointers gracefully (does nothing)
                    //

                    LocalFree ( szAt );
                    LocalFree ( NewResString );
                    LocalFree ( NewHzString );
                    LocalFree ( TotalString );

                    EndDialog(hDlg, LOWORD(wParam));
                    return (TRUE);

                    break;

                default:

                    break;

            } // switch (wParam)

            break;

       default:

             break;

    } // switch (message)


    return (FALSE);     // Didn't process a message


} // KeepNewResDlgProc()



//
//*****************************************************************************
//
//  NTOptionsDlgProc(HWND, UINT, WPARAM, LPARAM )
//
//
//
//*****************************************************************************
//

INT_PTR FAR PASCAL NTOptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    INT i;
    static WORD SaveQRFlags;

    switch (message)
    {

        case WM_INITDIALOG:

            //
            // Stop processing tray messages; check buttons properly
            //

            Waiting = TRUE;
            SaveQRFlags = QuickResFlags;

            CheckRadioButton(hDlg,IDD_SORT_RES,IDD_SORT_BPP,
                                  (fSortByBPP ? IDD_SORT_BPP : IDD_SORT_RES) );
            CheckRadioButton(hDlg,IDD_SUBMENUS,IDD_ALLMODEMENU, FreqMenuLocation );

            CheckDlgButton(hDlg, IDD_UPDATEREG, fUpdateReg );
            CheckDlgButton(hDlg, IDD_REMMODES,  fRememberModes );
            CheckDlgButton(hDlg, IDD_RESTARTREQ,  fShowModesThatNeedRestart );
            CheckDlgButton(hDlg, IDD_SHOWTESTED,  fShowTestedModes );

            return TRUE;
            break;


        case WM_COMMAND:


            switch (LOWORD(wParam))

            {

                //
                //  Update buttons : sorting by BPP or Res?
                //

                case IDD_SORT_RES:
                case IDD_SORT_BPP:
                    CheckRadioButton(hDlg,IDD_SORT_RES,IDD_SORT_BPP,LOWORD(wParam));
                    return TRUE;
                    break;

                //
                //  Update buttons : where to display freq menus?
                //

                case IDD_SUBMENUS:
                case IDD_ONEMENUMOBILE:
                case IDD_ONEMENUBOTTOM:
                case IDD_ALLMODEMENU:
                    CheckRadioButton(hDlg,IDD_SUBMENUS,IDD_ALLMODEMENU,LOWORD(wParam));
                    return TRUE;
                    break;


                //
                //  Clear all registry remembered settings
                //  Make user verify he did this on purpose
                //

                case IDD_CLEARREG:
                    if (MsgBox(IDS_CLEARREG,
                               0,
                               MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL)
                         ==    IDYES)
                    {

                        //
                        //  Reset flags for all monitors; destroy and rebuild
                        //  each mode menu
                        //

                        for (i=0; i<iMonitors; i++)
                        {
                            SetDevmodeFlags(i, TRUE);
                            VALIDMODE(pMonitors[i].pCurrentdm) = MODE_BESTHZ;
                            DestroyModeMenu( i, TRUE, FALSE);
                        }
                    }

                    return TRUE;
                    break;


                //
                //  XOR QuickResFlags on and off
                //

                case IDD_UPDATEREG:
                    QuickResFlags ^= QF_UPDATEREG;
                    return TRUE;
                    break;

                case IDD_REMMODES:
                    QuickResFlags ^= QF_REMMODES;
                    return TRUE;
                    break;

                case IDD_RESTARTREQ:
                    QuickResFlags ^= QF_SHOWRESTART;
                    return TRUE;
                    break;

                case IDD_SHOWTESTED:
                    QuickResFlags ^= QF_SHOWTESTED;
                    return TRUE;
                    break;


                case IDOK:
                {

                    BOOL bRebuildMenu   = FALSE;
                    BOOL bNeedToSort    = FALSE;


                    //
                    //  See if sort order has changed.
                    //

                    if ( (IsDlgButtonChecked (hDlg, IDD_SORT_RES) &&  fSortByBPP) ||
                         (IsDlgButtonChecked (hDlg, IDD_SORT_BPP) && !fSortByBPP) )
                    {
                        QuickResFlags ^= QF_SORT_BYBPP;
                        bNeedToSort = TRUE;
                    }


                    //
                    //  If "show modes that require restart", or "show tested "modes only",
                    //  then rebuild menu is required
                    //

                    if ( (fShowModesThatNeedRestart != (SaveQRFlags & QF_SHOWRESTART)) ||
                         (fShowTestedModes          != (SaveQRFlags & QF_SHOWTESTED))
                       )
                    {
                        bRebuildMenu = TRUE;
                    }



                    //
                    // see if FreqMenuLocation has changed
                    //

                    if (!IsDlgButtonChecked (hDlg, FreqMenuLocation))
                    {
                        WORD i;

                        //
                        //  Freq menu location has changed; update & ask for rebuild
                        //

                        bRebuildMenu = TRUE;

                        for ( i=IDD_SUBMENUS; i <= IDD_ALLMODEMENU; i++ )
                        {
                            if (IsDlgButtonChecked (hDlg, i))
                            {
                                FreqMenuLocation = i;
                            }
                        }
                    }


                    //
                    //  If rebuilding and or resorting, just destroy & rebuild the menus
                    //

                    if ( bNeedToSort || bRebuildMenu )
                    {
                        for (i=0; i<iMonitors; i++)
                            DestroyModeMenu( i, TRUE, bNeedToSort);
                    }

                    SaveAllSettings();

                    Waiting = FALSE;
                    EndDialog(hDlg, LOWORD(wParam));
                    return TRUE;
                    break;
                }

                case IDCANCEL :

                    Waiting = FALSE;
                    QuickResFlags = SaveQRFlags;
                    EndDialog(hDlg, LOWORD(wParam));
                    return TRUE;
                    break;

                default:

                    break;

            } // switch (wParam)

            break;

       default:

             break;

    } // switch (message)


    return FALSE;     // Didn't process a message


} // NTOptionsDlgProc()



//
//*****************************************************************************
//
//  W95OptionsDlgProc(HWND, UINT, WPARAM, LPARAM )
//
//
//
//*****************************************************************************
//

INT_PTR FAR PASCAL W95OptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{

    INT i;
    static WORD SaveQRFlags;

    switch (message)
    {

        case WM_INITDIALOG:

            //
            // Stop processing tray messages; check buttons properly
            //

            Waiting = TRUE;
            SaveQRFlags = QuickResFlags;

            CheckRadioButton(hDlg,IDD_SORT_RES,IDD_SORT_BPP,
                                  (fSortByBPP ? IDD_SORT_BPP : IDD_SORT_RES) );

            CheckDlgButton(hDlg, IDD_UPDATEREG, fUpdateReg );
            CheckDlgButton(hDlg, IDD_REMMODES,  fRememberModes );
            CheckDlgButton(hDlg, IDD_RESTARTREQ,  fShowModesThatNeedRestart );
            CheckDlgButton(hDlg, IDD_SHOWTESTED,  fShowTestedModes );

            return TRUE;
            break;


        case WM_COMMAND:


            switch (LOWORD(wParam))

            {

                //
                //  Update buttons : sorting by BPP or Res?
                //

                case IDD_SORT_RES:
                case IDD_SORT_BPP:
                    CheckRadioButton(hDlg,IDD_SORT_RES,IDD_SORT_BPP,LOWORD(wParam));
                    return TRUE;
                    break;

                //
                //  Clear all registry remembered settings
                //  Make user verify he did this on purpose
                //

                case IDD_CLEARREG:
                    if (MsgBox(IDS_CLEARREG,
                               0,
                               MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL)
                         ==    IDYES)
                    {

                        //
                        //  Reset flags for all monitors; destroy and rebuild
                        //  each mode menu
                        //

                        for (i=0; i<iMonitors; i++)
                        {
                            SetDevmodeFlags(i, TRUE);
                            VALIDMODE(pMonitors[i].pCurrentdm) = MODE_BESTHZ;
                            DestroyModeMenu( i, TRUE, FALSE);
                        }
                    }

                    return TRUE;
                    break;


                //
                //  XOR QuickResFlags on and off
                //

                case IDD_UPDATEREG:
                    QuickResFlags ^= QF_UPDATEREG;
                    return TRUE;
                    break;

                case IDD_REMMODES:
                    QuickResFlags ^= QF_REMMODES;
                    return TRUE;
                    break;

                case IDD_RESTARTREQ:
                    QuickResFlags ^= QF_SHOWRESTART;
                    return TRUE;
                    break;

                case IDD_SHOWTESTED:
                    QuickResFlags ^= QF_SHOWTESTED;
                    return TRUE;
                    break;

                case IDOK:
                {
                    BOOL bNeedToSort = FALSE;

                    //
                    //  Note if the sort order has changed
                    //

                    if ( (IsDlgButtonChecked (hDlg, IDD_SORT_RES) &&  fSortByBPP) ||
                         (IsDlgButtonChecked (hDlg, IDD_SORT_BPP) && !fSortByBPP) )
                    {
                        QuickResFlags ^= QF_SORT_BYBPP;
                        bNeedToSort = TRUE;
                    }


                    //
                    //  If "sort order", "show modes that require restart", or "show tested
                    //  "modes only" changed, then destroy and rebuild old menu (resort if nec.)
                    //

                    if ( bNeedToSort ||
                         (fShowModesThatNeedRestart != (SaveQRFlags & QF_SHOWRESTART)) ||
                         (fShowTestedModes          != (SaveQRFlags & QF_SHOWTESTED))
                       )
                    {
                        for (i=0; i<iMonitors; i++)
                            DestroyModeMenu( i, TRUE, bNeedToSort);
                    }

                    SaveAllSettings();

                    //
                    //  No break after IDOK, by design.
                    //  IDOK AND IDCANCEL : start processing tray clicks,
                    //  and return ok/cancel as return value.
                    //
                }

                case IDCANCEL :

                    Waiting = FALSE;
                    EndDialog(hDlg, LOWORD(wParam));
                    return TRUE;
                    break;

                default:

                    break;

            } // switch (wParam)

            break;

       default:

             break;

    } // switch (message)


    return FALSE;     // Didn't process a message


} // W95OptionsDlgProc()
