Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1343 lines
39 KiB

//////////////////////////////////////////////////////////////////////////
//
// dlgapp.cpp
//
// This file contains the main entry point into the application and
// the implementation of the CDlgApp class.
//
// (C) Copyright 1997 by Microsoft Corporation. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <commctrl.h>
#include <shlwapi.h> // for string compare functions
#include <debug.h>
#include <tchar.h>
#include <winuser.h>
#pragma hdrstop
#include "autorun.h"
#include "dlgapp.h"
#include "dataitem.h"
#include "resource.h"
WNDPROC g_fnBtnProc; // the window proc for a button.
//////////////////////////////////////////////////////////////////////////
// #defines
//////////////////////////////////////////////////////////////////////////
// todo: generate these dynamically
#define FLAG_HEIGHT 43
#define FLAG_WIDTH 47
#define HEADER_HEIGHT 48
#define HEADER_WIDTH 48
#define MENUICON_HEIGHT 29
#define MENUICON_WIDTH 28
//////////////////////////////////////////////////////////////////////////
// Code
//////////////////////////////////////////////////////////////////////////
/**
* This method is our contstructor for our class. It initialize all
* of the instance data.
*/
CDlgApp::CDlgApp()
{
m_fTaskRunning = FALSE;
m_iSelectedItem = -1;
g_fnBtnProc = NULL;
m_hInstance = NULL;
m_hwnd = NULL;
m_fHighContrast = FALSE;
m_hfontTitle = NULL;
m_hfontHeader = NULL;
m_hfontMenu = NULL;
m_hbrTopPanel = NULL;
m_hbrCenterPanel = NULL;
m_hbrBottomPanel = NULL;
m_szTitle[0] = NULL;
m_szHeader[0] = NULL;
// store desktop width
RECT rcDesktop;
SystemParametersInfo(SPI_GETWORKAREA,0, &rcDesktop, FALSE);
m_cDesktopWidth = rcDesktop.right - rcDesktop.left;
m_cDesktopHeight = rcDesktop.bottom - rcDesktop.top;
if (m_cDesktopWidth >= 800)
{
m_f8by6 = TRUE;
}
else
{
m_f8by6 = FALSE;
}
m_hdcFlag = NULL;
m_hdcHeader = NULL;
m_hdcHeaderSub = NULL;
m_hdcGradientTop = NULL;
m_hdcGradientTop256 = NULL;
m_hdcGradientBottom = NULL;
m_hdcGradientBottom256 = NULL;
m_hdcCloudsFlag = NULL;
m_hdcCloudsFlag256 = NULL;
m_hdcCloudsFlagRTL = NULL;
m_hdcCloudsFlagRTL256 = NULL;
for (int i = 0; i < ARRAYSIZE(m_rghdcArrows); i++)
{
for (int j = 0; j < ARRAYSIZE(m_rghdcArrows[0]); j++)
{
for (int k = 0; k < ARRAYSIZE(m_rghdcArrows[0][0]); k++)
{
m_rghdcArrows[i][j][k] = NULL;
}
}
}
m_hcurHand = NULL;
m_dwScreen = SCREEN_MAIN;
m_fLowColor = FALSE;
m_iColors = -1;
m_hpal = NULL;
}
CDlgApp::~CDlgApp()
{
DeleteObject(m_hfontTitle);
DeleteObject(m_hfontHeader);
DeleteObject(m_hfontMenu);
DeleteObject(m_hbrTopPanel);
DeleteObject(m_hbrCenterPanel);
DeleteObject(m_hbrBottomPanel);
DeleteDC(m_hdcFlag);
DeleteDC(m_hdcHeader);
DeleteDC(m_hdcHeaderSub);
DeleteDC(m_hdcGradientTop);
DeleteDC(m_hdcGradientTop256);
DeleteDC(m_hdcGradientBottom);
DeleteDC(m_hdcGradientBottom256);
DeleteDC(m_hdcCloudsFlag);
DeleteDC(m_hdcCloudsFlag256);
DeleteDC(m_hdcCloudsFlagRTL);
DeleteDC(m_hdcCloudsFlagRTL256);
for (int i = 0; i < ARRAYSIZE(m_rghdcArrows); i++)
{
for (int j = 0; j < ARRAYSIZE(m_rghdcArrows[0]); j++)
{
for (int k = 0; k < ARRAYSIZE(m_rghdcArrows[0][0]); k++)
{
DeleteDC(m_rghdcArrows[i][j][k]);
}
}
}
}
/**
* This method will register our window class for the application.
*
* @param hInstance The application instance handle.
*
* @return No return value.
*/
void CDlgApp::Register(HINSTANCE hInstance)
{
WNDCLASS wndclass;
m_hInstance = hInstance;
wndclass.style = CS_OWNDC | CS_DBLCLKS;
wndclass.lpfnWndProc = s_WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WEBAPP));
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = WINDOW_CLASS;
RegisterClass(&wndclass);
}
/**
* This method will initialize the data object.
*
* @return No return value.
*/
BOOL CDlgApp::InitializeData(LPSTR pszCommandLine)
{
HWND hwnd = GetDesktopWindow();
HDC hdc = GetDC( hwnd );
m_iColors = GetDeviceCaps( hdc, NUMCOLORS );
m_fLowColor = ((m_iColors != -1) && (m_iColors <= 256));
if ( m_fLowColor )
{
m_hpal = CreateHalftonePalette(hdc);
}
// Initialize the items from the INI file.
if ( !m_DataSrc.Init(pszCommandLine) )
{
// this is a sign from the data source that we should exit
return FALSE;
}
// Are we in accesibility mode? This call won't work on NT 4.0 because this flag wasn't known.
HIGHCONTRAST hc;
hc.cbSize = sizeof(HIGHCONTRAST);
hc.dwFlags = 0; // avoid random result should SPI fail
if ( SystemParametersInfo( SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), &hc, 0 ) )
{
m_fHighContrast = ( hc.dwFlags & HCF_HIGHCONTRASTON );
}
// 210679: go to HighContrast mode if we're in 16-color mode as well
if ( m_fLowColor && (m_iColors <= 16))
{
m_fHighContrast = TRUE;
}
// Set the color table based on our HighContrast mode setting.
_SetColorTable();
// create the fonts that we need to use.
_CreateFonts(hdc);
// create the images
_CreateBitmaps();
_CreateArrowBitmaps();
_CreateGradientBitmaps();
// load the resource strings that we always need
LoadStringAuto( m_hInstance, IDS_TITLE, m_szTitle, ARRAYSIZE(m_szTitle) );
LoadStringAuto( m_hInstance, IDS_HEADER, m_szHeader, ARRAYSIZE(m_szHeader) );
m_hcurHand = LoadCursor( m_hInstance, MAKEINTRESOURCE(IDC_BRHAND) );
ReleaseDC( hwnd, hdc );
return TRUE;
}
#if BUILD_SERVER_VERSION | BUILD_ADVANCED_SERVER_VERSION | BUILD_DATACENTER_VERSION | BUILD_BLADE_VERSION | BUILD_SMALL_BUSINESS_VERSION
#define CENTER_RGB_VALUES RGB(122,131,137)
#define PANEL_RGB_VALUES RGB(63,70,76)
#define DISABLED_RGB_VALUES RGB(64, 64, 64)
#else
#define CENTER_RGB_VALUES RGB(90,126,220)
#define PANEL_RGB_VALUES RGB(59,52,177)
#define DISABLED_RGB_VALUES RGB(128, 128, 128)
#endif
#define TITLE_RGB_VALUES RGB(255, 255, 255)
#define HEADER_RGB_VALUES RGB(214, 223, 245)
#define SHADOW_RGB_VALUES RGB(52, 98, 189)
#define TEXT_RGB_VALUES RGB(255, 255, 255)
BOOL CDlgApp::_SetColorTable()
{
if ( m_fHighContrast )
{
// set to high contrast values
m_hbrTopPanel = (HBRUSH)(COLOR_BTNFACE+1);
m_hbrCenterPanel = (HBRUSH)(COLOR_WINDOW+1);
m_hbrBottomPanel = (HBRUSH)(COLOR_BTNFACE+1);
m_crNormalText = GetSysColor(COLOR_WINDOWTEXT);
m_crTitleText = m_crNormalText;
m_crHeaderText = m_crNormalText;
m_crDisabledText = GetSysColor(COLOR_GRAYTEXT);
m_crCenterPanel = GetSysColor(COLOR_WINDOW);
m_crBottomPanel = GetSysColor(COLOR_WINDOW);
}
else
{
m_crTitleText = TITLE_RGB_VALUES;
m_crHeaderText = HEADER_RGB_VALUES;
m_crShadow = SHADOW_RGB_VALUES;
m_crNormalText = TEXT_RGB_VALUES;
m_crDisabledText = DISABLED_RGB_VALUES;
m_crCenterPanel = CENTER_RGB_VALUES;
m_crBottomPanel = PANEL_RGB_VALUES;
if ( m_fLowColor )
{
HBITMAP hbmp;
hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_TOP), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
if (hbmp)
{
m_hbrTopPanel = CreatePatternBrush(hbmp);
DeleteObject(hbmp);
}
else
m_hbrTopPanel = (HBRUSH)(COLOR_BTNFACE+1);
hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_BOTTOM), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
if (hbmp)
{
m_hbrBottomPanel = CreatePatternBrush(hbmp);
DeleteObject(hbmp);
}
else
m_hbrBottomPanel = (HBRUSH)(COLOR_BTNFACE+1);
hbmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_CENTER), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
if (hbmp)
{
m_hbrCenterPanel = CreatePatternBrush(hbmp);
DeleteObject(hbmp);
}
else
m_hbrCenterPanel = (HBRUSH)(COLOR_WINDOW+1);
}
else
{
m_hbrTopPanel = CreateSolidBrush( PANEL_RGB_VALUES );
m_hbrCenterPanel = CreateSolidBrush( CENTER_RGB_VALUES );
m_hbrBottomPanel= CreateSolidBrush ( PANEL_RGB_VALUES );
}
}
return TRUE;
}
// this is called once for each font that matches the fonts we care about
int CALLBACK FoundFont
(
ENUMLOGFONTEX *lpelfe, // logical-font data
NEWTEXTMETRICEX *lpntme, // physical-font data
DWORD FontType, // type of font
LPARAM lParam // application-defined data
)
{
*((BOOL*)lParam) = TRUE;
return 0;
}
#define RGFONTDEX_LARGE 0
#define RGFONTDEX_SMALL 1
#define RGFONTDEX_TITLE 0
#define RGFONTDEX_HEADER 1
#define RGFONTDEX_MENU 2
#define RGFONTDEX_FULL 0
#define RGFONTDEX_BACKUP 1
BOOL CDlgApp::_CreateFonts(HDC hdc)
{
// [in] array of IDs, arranged by {title, header, menu} x { nice font, backup font}
const int rgFontID[3][2] =
{{IDS_FONTFACE_TITLE, IDS_FONTFACE_TITLE_BACKUP},
{IDS_FONTFACE_HEADER,IDS_FONTFACE_HEADER_BACKUP},
{IDS_FONTFACE_MENU, IDS_FONTFACE_MENU_BACKUP}};
// [in] array of heights, arranged by {large x small} x {title, header, menu} x { nice font, backup font}
const int rgFontHeight[2][3][2] =
{{{IDS_FONTCY_TITLE, IDS_FONTCY_TITLE_BACKUP},
{IDS_FONTCY_HEADER, IDS_FONTCY_HEADER_BACKUP},
{IDS_FONTCY_MENU, IDS_FONTCY_MENU_BACKUP}},
{{IDS_FONTCY_TITLE_LIL, IDS_FONTCY_TITLE_BACKUP_LIL},
{IDS_FONTCY_HEADER_LIL, IDS_FONTCY_HEADER_BACKUP_LIL},
{IDS_FONTCY_MENU_LIL, IDS_FONTCY_MENU_BACKUP_LIL}}};
// [out] array of pointers to the fonts
HFONT* rgpFont[3] = {&m_hfontTitle, &m_hfontHeader, &m_hfontMenu};
// [out] array of pointers heights of each font
int* rgpcyFont[3] = {&m_cTitleFontHeight, &m_cHeaderFontHeight, &m_cMenuFontHeight};
LOGFONT lf;
CHARSETINFO csInfo;
TCHAR szFontSize[6];
for (int i = 0; i < ARRAYSIZE(rgpFont); i++)
{
ZeroMemory(&lf,sizeof(lf));
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = DEFAULT_PITCH|FF_SWISS;
LoadStringAuto( m_hInstance, rgFontID[i][RGFONTDEX_FULL], lf.lfFaceName, ARRAYSIZE(lf.lfFaceName) );
// Set charset
if (TranslateCharsetInfo((DWORD*)IntToPtr(GetACP()), &csInfo, TCI_SRCCODEPAGE) == 0)
{
csInfo.ciCharset = 0;
}
lf.lfCharSet = (BYTE)csInfo.ciCharset;
LoadStringAuto( m_hInstance, rgFontHeight[m_f8by6 ? 0 : 1][i][RGFONTDEX_FULL], szFontSize, ARRAYSIZE(szFontSize) );
*(rgpcyFont[i]) = _ttoi(szFontSize);
lf.lfHeight = -(*(rgpcyFont[i]));
BOOL fFound = FALSE;
EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)FoundFont, (LPARAM)&fFound, 0);
if (!fFound)
{
LoadStringAuto( m_hInstance, rgFontID[i][RGFONTDEX_BACKUP], lf.lfFaceName, ARRAYSIZE(lf.lfFaceName) );
LoadStringAuto( m_hInstance, rgFontHeight[m_f8by6 ? 0 : 1][i][RGFONTDEX_BACKUP], szFontSize, ARRAYSIZE(szFontSize) );
*(rgpcyFont[i]) = _ttoi(szFontSize);
lf.lfHeight = -(*(rgpcyFont[i]));
}
*(rgpFont[i]) = CreateFontIndirect(&lf);
}
return TRUE;
}
#define BITMAPTYPE_NORMAL 0x0
#define BITMAPTYPE_LOWCOLOR 0x1
BOOL CDlgApp::_CreateBitmaps()
{
const int rgiBitmapID[3][2] = {{ IDB_FLAG, IDB_FLAG_256},
{ IDB_HEADER, IDB_HEADER_256} ,
{ IDB_HEADERSUB, IDB_HEADERSUB_256} }; // [in]
HDC* rgphdc[3] = {&m_hdcFlag, &m_hdcHeader, &m_hdcHeaderSub}; // [out]
int iBitmapType = (m_fLowColor) ? BITMAPTYPE_LOWCOLOR : BITMAPTYPE_NORMAL;
for (int i = 0; i < ARRAYSIZE(rgphdc); i++)
{
HBITMAP hbm;
BITMAP bm;
*(rgphdc[i]) = CreateCompatibleDC(NULL);
hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i][iBitmapType]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
GetObject(hbm,sizeof(bm),&bm);
SelectObject( *(rgphdc[i]), hbm );
}
return TRUE;
}
BOOL CDlgApp::_CreateArrowBitmaps()
{
const int rgiBitmapID[2][4][3] =
{{{IDB_YELLOW, IDB_YELLOW_HOVER, IDB_YELLOW_DISABLED},
{IDB_RED, IDB_RED_HOVER, IDB_RED_DISABLED},
{IDB_GREEN, IDB_GREEN_HOVER, IDB_GREEN_DISABLED},
{IDB_BLUE, IDB_BLUE_HOVER, IDB_BLUE_DISABLED}},
{{IDB_YELLOW_256, IDB_YELLOW_HOVER_256, IDB_YELLOW_DISABLED_256},
{IDB_RED_256, IDB_RED_HOVER_256, IDB_RED_DISABLED_256},
{IDB_GREEN_256, IDB_GREEN_HOVER_256, IDB_GREEN_DISABLED_256},
{IDB_BLUE_256, IDB_BLUE_HOVER_256, IDB_BLUE_DISABLED_256}}}; // [in]
for (int i = 0; i < ARRAYSIZE(m_rghdcArrows); i++)
{
for (int j = 0; j < ARRAYSIZE(m_rghdcArrows[0]); j++)
{
for (int k = 0; k < ARRAYSIZE(m_rghdcArrows[0][0]); k++)
{
HBITMAP hbm;
BITMAP bm;
m_rghdcArrows[i][j][k] = CreateCompatibleDC(NULL);
hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i][j][k]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
GetObject(hbm,sizeof(bm),&bm);
SelectObject( m_rghdcArrows[i][j][k], hbm );
}
}
}
return TRUE;
}
BOOL CDlgApp::_CreateGradientBitmaps()
{
const int rgiBitmapID[8] = {IDB_GRADIENT_TOP, IDB_GRADIENT_TOP_256, IDB_GRADIENT_BOTTOM, IDB_GRADIENT_BOTTOM_256, IDB_CLOUDSFLAG, IDB_CLOUDSFLAG_256, IDB_CLOUDSFLAG_RTL, IDB_CLOUDSFLAG_RTL_256}; // [in]
HDC* rgphdc[8] = {&m_hdcGradientTop, &m_hdcGradientTop256, &m_hdcGradientBottom, &m_hdcGradientBottom256, &m_hdcCloudsFlag, &m_hdcCloudsFlag256, &m_hdcCloudsFlagRTL, &m_hdcCloudsFlagRTL256}; // [out]
for (int i = 0; i < ARRAYSIZE(rgphdc); i++)
{
HBITMAP hbm;
BITMAP bm;
*(rgphdc[i]) = CreateCompatibleDC(NULL);
hbm = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(rgiBitmapID[i]), IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION);
GetObject(hbm,sizeof(bm),&bm);
SelectObject( *(rgphdc[i]), hbm );
}
return TRUE;
}
BOOL CDlgApp::_GetLargestStringWidth(HDC hdc, SIZE* psize)
{
SIZE sCurr = {0};
psize->cx = 0;
psize->cy = 0;
for (int i = 0; i < MAX_OPTIONS; i++)
{
if (GetTextExtentPoint32(hdc, m_DataSrc[i].GetTitle(), lstrlen(m_DataSrc[i].GetTitle()), &sCurr))
{
if (sCurr.cx > psize->cx)
{
memcpy(psize, &sCurr, sizeof(SIZE));
}
}
}
return (psize->cx > 0);
}
#define MENUITEMCX(x) (m_f8by6 ? 270 : 210)
#define MENUITEMCY(x) ((m_f8by6 ? 245 : 197) + ((x - 1) * (m_f8by6 ? 45 : 30)))
#define MENUEXITCX(x) (m_f8by6 ? 75 : 63)
#define MENUEXITCY(x) (m_f8by6 ? 540 : 406)
BOOL CDlgApp::_AdjustToFitFonts()
{
HDC hdc = GetDC(m_hwnd);
if (hdc)
{
SetMapMode(hdc,MM_TEXT);
// don't check for error, if these fail we're totally screwed anyway
SIZE sizeLargest, sizeExit = {0};
_GetLargestStringWidth(hdc, &sizeLargest);
GetTextExtentPoint32(hdc, m_DataSrc[0].GetTitle(), lstrlen(m_DataSrc[0].GetTitle()), &sizeExit);
for (int i=0; i < MAX_MENUITEMS; i++ )
{
DWORD dwType = m_DataSrc[i].m_dwType;
HWND hwnd = GetDlgItem(m_hwnd, IDM_MENUITEM0+i);
SIZE* psize = (i == 0) ? &sizeExit: &sizeLargest;
SetWindowPos(hwnd, NULL,
(i == 0) ? MENUEXITCX(i) : MENUITEMCX(i),
(i == 0) ? MENUEXITCY(i) : MENUITEMCY(i),
(psize->cx * 3) / 2, (psize->cy * 3) / 2, SWP_NOZORDER );
}
ReleaseDC(m_hwnd, hdc);
}
return TRUE;
}
#define MENUARROWCX(x) (m_f8by6 ? 232 : 177)
#define MENUARROWCY(x) ((m_f8by6 ? 244 : 194) + ((x - 1)* (m_f8by6 ? 45 : 30)))
#define EXITARROWCX(x) (m_f8by6 ? 42 : 32)
#define EXITARROWCY(x) (m_f8by6 ? 537 : 403)
#define ARROWBITMAPSTUFF(rgarrows) if (WF_DISABLED & m_DataSrc[i].m_dwFlags) { phdcBitmap = &(rgarrows[2]); } else { phdcBitmap = (m_iSelectedItem == i) ? &(rgarrows[1]) : &(rgarrows[0]); }
#define EXITARROWBITMAPSTUFF(rgarrows) {phdcBitmap = (m_iSelectedItem == i) ? &(rgarrows[1]) : &(rgarrows[0]);}
BOOL CDlgApp::_DrawMenuIcons(BOOL fEraseBackground)
{
HDC hdc = GetDC(m_hwnd);
if (hdc)
{
for (int i=0; i< m_DataSrc.m_iItems; i++ )
{
RECT rect;
HDC* phdcBitmap;
DWORD dwType = m_DataSrc[i].m_dwType;
switch (dwType)
{
case INSTALL_WINNT: // special
ARROWBITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][2]);
break;
case EXIT_AUTORUN: // exit
EXITARROWBITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][1]);
break;
case BACK: // back icon
ARROWBITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][0]);
break;
default: // normal icon for everything else
ARROWBITMAPSTUFF(m_rghdcArrows[m_fLowColor ? 1 : 0][3]);
break;
}
rect.left = (i == 0) ? (EXITARROWCX(i)) : (MENUARROWCX(i));
rect.top = (i == 0) ? (EXITARROWCY(i)) : (MENUARROWCY(i));
rect.right = rect.left + MENUICON_WIDTH; // arrow width
rect.bottom = rect.top + MENUICON_HEIGHT; // arrow height as well
BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, *phdcBitmap, 0,0, SRCCOPY );
_InvalidateRectIntl(m_hwnd, &rect, FALSE);
}
ReleaseDC(m_hwnd, hdc);
}
// clear any old icons as well
RECT rect;
rect.left = MENUARROWCX(0);
rect.right = rect.left + MENUICON_WIDTH; // arrow width
rect.top = MENUARROWCY(0);
rect.bottom = m_cyClient;
_InvalidateRectIntl(m_hwnd, &rect, fEraseBackground);
return TRUE;
}
void CDlgApp::_InvalidateRectIntl(HWND hwnd, RECT* pRect, BOOL fBackgroundClear)
{
RECT* pRectToUse = pRect; // default to normal case (don't flip)
RECT rectRTL;
if (pRect)
{
OSVERSIONINFO osvi;
if (GetVersionEx(&osvi) &&
(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
Mirror_IsWindowMirroredRTL(hwnd)) // right to left on Win9X
{
rectRTL.top = pRect->top; rectRTL.bottom = pRect->bottom;
rectRTL.right = m_cxClient - pRect->left;
rectRTL.left = m_cxClient - pRect->right;
pRectToUse = &rectRTL;
}
}
InvalidateRect(hwnd, pRectToUse, fBackgroundClear);
}
/**
* This method will create the application window.
*
* @return No return value.
*/
void CDlgApp::Create(int nCmdShow)
{
//
// load the window title from the resource.
//
TCHAR szTitle[MAX_PATH];
LoadStringAuto(m_hInstance, IDS_TITLEBAR, szTitle, ARRAYSIZE(szTitle));
DWORD dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_CLIPCHILDREN;
if (m_cDesktopWidth >= 800)
{
m_cxClient = 800;
m_cyClient = 600;
}
else
{
m_cxClient = 640;
m_cyClient = 480;
}
m_hwnd = CreateWindowEx(
WS_EX_CONTROLPARENT,
WINDOW_CLASS,
szTitle,
dwStyle,
0,
0,
m_cxClient,
m_cyClient,
NULL,
NULL,
m_hInstance,
this);
// set the client area to a fixed size and center the window on screen
RECT rect = {0};
rect.left = (m_cDesktopWidth - m_cxClient) / 2;
rect.top = (m_cDesktopHeight - m_cyClient) / 2;
rect.right = m_cDesktopWidth - rect.left;
rect.bottom = m_cDesktopHeight - rect.top;
AdjustWindowRect( &rect, dwStyle, FALSE );
SetWindowPos(m_hwnd, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
ShowWindow(m_hwnd, SW_SHOW);
m_cxTopPanel = m_f8by6 ? 80 : 64;
m_cyBottomPanel = m_f8by6 ? 501 : 381;
m_DataSrc.SetWindow( m_hwnd );
_InvalidateRectIntl(m_hwnd, NULL, TRUE);
UpdateWindow(m_hwnd);
}
/**
* This method is our application message loop.
*
* @return No return value.
*/
void CDlgApp::MessageLoop()
{
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
// IsDialogMessage cannot understand the concept of ownerdraw default pushbuttons. It treats
// these attributes as mutually exclusive. As a result, we handle this ourselves. We want
// whatever control has focus to act as the default pushbutton.
if ( (WM_KEYDOWN == msg.message) && (VK_RETURN == msg.wParam) )
{
HWND hwndFocus = GetFocus();
if ( hwndFocus )
{
SendMessage(m_hwnd, WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndFocus), BN_CLICKED), (LPARAM)hwndFocus);
}
continue;
}
if ( IsDialogMessage(m_hwnd, &msg) )
continue;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/**
* This is the window procedure for the container application. It is used
* to deal with all messages to our window.
*
* @param hwnd Window handle.
* @param msg The window message.
* @param wParam Window Parameter.
* @param lParam Window Parameter.
*
* @return LRESULT
*/
LRESULT CALLBACK CDlgApp::s_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CDlgApp *pThis = (CDlgApp *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
switch(msg)
{
case WM_NCCREATE:
{
CDlgApp* pThisCreate = (CDlgApp *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LRESULT)pThisCreate);
}
break;
case WM_CREATE:
return pThis->OnCreate(hwnd);
case WM_DESTROY:
return pThis->OnDestroy();
case WM_ACTIVATE:
return pThis->OnActivate(wParam);
case WM_PAINT:
return pThis->OnPaint((HDC)wParam);
case WM_ERASEBKGND:
return pThis->OnEraseBkgnd((HDC)wParam);
case WM_LBUTTONUP:
return pThis->OnLButtonUp(LOWORD(lParam), HIWORD(lParam), (DWORD)wParam);
case WM_MOUSEMOVE:
return pThis->OnMouseMove(LOWORD(lParam), HIWORD(lParam), (DWORD)wParam);
case WM_SETCURSOR:
return pThis->OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
case WM_COMMAND:
case WM_SYSCOMMAND:
if ( pThis->OnCommand(LOWORD(wParam)) )
return 0;
break;
case WM_DRAWITEM:
return pThis->OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
case WM_QUERYNEWPALETTE:
return pThis->OnQueryNewPalette();
case WM_PALETTECHANGED:
return pThis->OnPaletteChanged((HWND)wParam);
case ARM_CHANGESCREEN:
return pThis->OnChangeScreen((DWORD)wParam);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
/**
* This method is called on WM_CREATE.
*
* @param hwnd Window handle for the application.
*
* @return No return value.
*/
LRESULT CDlgApp::OnCreate(HWND hwnd)
{
m_hwnd = hwnd;
_CreateMenu();
_RedrawMenu();
return 0;
}
void CDlgApp::_CreateMenu()
{
// Create one window for each button. These windows will get resized and moved
// after we call AdjustToFitFonts.
for (int i=0; i<MAX_MENUITEMS; i++)
{
HWND hwnd = CreateWindowEx(
0,
TEXT("BUTTON"),
TEXT(""),
WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON|BS_MULTILINE|BS_OWNERDRAW,
0,0,0,0,
m_hwnd,
NULL,
m_hInstance,
NULL );
SetWindowLongPtr(hwnd, GWLP_ID, IDM_MENUITEM0 + i);
SendMessage(hwnd, WM_SETFONT, (WPARAM)m_hfontMenu, 0);
g_fnBtnProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)s_ButtonWndProc);
EnableWindow(hwnd, i < m_DataSrc.m_iItems);
}
// Set focus to first menu item
SetFocus(GetDlgItem(m_hwnd, IDM_MENUITEM1));
// We created the windows with zero size, now we adjust that size to take into
// account for the selected font size, etc.
_AdjustToFitFonts();
}
void CDlgApp::_RedrawMenu()
{
for (int i=0; i < MAX_MENUITEMS; i++)
{
// setting window text only actually sets the accelerator, real drawing of text is in OnDrawItem
SetWindowText(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), (i < m_DataSrc.m_iItems) ? m_DataSrc[i].GetTitle() : TEXT(""));
EnableWindow(GetDlgItem(m_hwnd, IDM_MENUITEM0+i), (i < m_DataSrc.m_iItems));
}
}
/**
* This method handles the WM_DESTROY message.
*
* @return No return value.
*/
LRESULT CDlgApp::OnDestroy()
{
// ensure this is the last message we care about
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
PostQuitMessage(0);
return 0;
}
LRESULT CDlgApp::OnActivate(WPARAM wParam)
{
return 0;
}
/**
* This method handles the WM_PAINT message.
*
* @return No return value.
*/
LRESULT CDlgApp::OnPaint(HDC hdc)
{
// this code makes the window look better when being dragged around
PAINTSTRUCT ps;
BeginPaint(m_hwnd,&ps);
EndPaint(m_hwnd,&ps);
return 0;
}
/**
* This method handles the WM_ERASEBKGND message.
*
* @return No return value.
*/
LRESULT CDlgApp::OnEraseBkgnd(HDC hdc)
{
RECT rect;
HPALETTE hpalOld = NULL;
if ( m_hpal )
{
hpalOld = SelectPalette(hdc, m_hpal, FALSE);
RealizePalette(hdc);
}
SetMapMode(hdc, MM_TEXT);
SetBkMode(hdc, TRANSPARENT);
// Draw the top pane:
rect.left = 0;
rect.top = 0;
rect.right = m_cxClient;
rect.bottom = m_cxTopPanel;
if (m_f8by6 && !m_fLowColor)
{
BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hdcGradientTop, 0,0, SRCCOPY );
}
else if (m_f8by6 && m_fLowColor && (m_iColors > 16))
{
BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, m_hdcGradientTop256, 0,0, SRCCOPY );
}
else
{
FillRect(hdc, &rect, m_hbrTopPanel);
}
// Draw the center pane:
rect.left = 0;
rect.top = m_cxTopPanel;
rect.right = m_cxClient;
rect.bottom = m_cyBottomPanel;
FillRect(hdc, &rect, m_hbrCenterPanel);
// Drag the clouds/flag bitmap
if (m_f8by6)
{
rect.left = 0;
rect.top = m_cxTopPanel;
rect.right = 397;
rect.bottom = m_cxTopPanel + 180;
HDC hdcCloudsFlag;
if (Mirror_IsWindowMirroredRTL(m_hwnd))
{
hdcCloudsFlag = m_fLowColor? m_hdcCloudsFlagRTL256 : m_hdcCloudsFlagRTL;
}
else
{
hdcCloudsFlag = m_fLowColor? m_hdcCloudsFlag256 : m_hdcCloudsFlag;
}
BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdcCloudsFlag , 0,0, SRCCOPY | NOMIRRORBITMAP);
}
// Draw the bottom pane:
rect.left = 0;
rect.top = m_cyBottomPanel;
rect.right = m_cxClient;
rect.bottom = m_cyClient;
if (m_f8by6 && !m_fLowColor)
{
BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 1, m_hdcGradientBottom, 0,0, SRCCOPY );
}
else if (m_f8by6 && m_fLowColor && (m_iColors > 16))
{
BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top + 1, m_hdcGradientBottom256, 0,0, SRCCOPY );
}
else
{
FillRect(hdc, &rect, m_hbrBottomPanel);
}
// Draw the flag bitmap if in 640x480
if (!m_f8by6)
{
rect.left = 20;
rect.top = 80;
rect.right = rect.left + FLAG_WIDTH;
rect.bottom = rect.top + FLAG_HEIGHT;
BitBlt( hdc, rect.left, rect.top, FLAG_WIDTH, FLAG_HEIGHT, m_hdcFlag, 0,0, SRCCOPY | NOMIRRORBITMAP); // don't mirror flag on RTL systems for trademark reasons
}
// Draw the header bitmap:
_PaintHeaderBitmap();
// draw menu icons
_DrawMenuIcons(FALSE);
// draw header text
if (m_f8by6)
{
rect.left = 237;
rect.top = 192;
}
else
{
rect.left = 197;
rect.top = 142;
}
rect.right = rect.left + 400;
rect.bottom = rect.top + m_cHeaderFontHeight;
HFONT hfontOld = (HFONT)SelectObject(hdc,m_hfontHeader);
if ( !m_fHighContrast )
{
SetTextColor(hdc,m_crShadow);
DrawText(hdc,m_szHeader,-1,&rect,DT_NOCLIP|DT_WORDBREAK);
}
_InvalidateRectIntl(m_hwnd, &rect, FALSE);
rect.left -= 2; rect.right -= 2; rect.top -= 2; rect.bottom -= 2;
SetTextColor(hdc,m_crHeaderText);
DrawText(hdc,m_szHeader,-1,&rect,DT_NOCLIP|DT_WORDBREAK);
_InvalidateRectIntl(m_hwnd, &rect, FALSE);
// draw title text
if (m_f8by6)
{
rect.left = 97;
rect.top = 105;
}
else
{
rect.left = 72;
rect.top = 63;
}
rect.right = rect.left + 700;
rect.bottom = rect.top + m_cTitleFontHeight;
(HFONT)SelectObject(hdc,m_hfontTitle);
if ( !m_fHighContrast )
{
SetTextColor(hdc,m_crShadow);
DrawText(hdc,m_szTitle,-1,&rect,DT_NOCLIP|DT_WORDBREAK);
}
rect.left -= 2; rect.right -= 2; rect.top -= 2; rect.bottom -= 2;
SetTextColor(hdc,m_crTitleText);
DrawText(hdc,m_szTitle,-1,&rect,DT_NOCLIP|DT_WORDBREAK);
// restore the DC to its original value
SelectObject(hdc,hfontOld);
if(hpalOld)
SelectPalette(hdc, hpalOld, FALSE);
return TRUE;
}
void CDlgApp::_PaintHeaderBitmap()
{
HDC hdc = GetDC(m_hwnd);
if (hdc)
{
RECT rect;
if (m_f8by6)
{
rect.left = 177;
rect.top = 186;
}
else
{
rect.left = 137;
rect.top = 133;
}
rect.right = rect.left + HEADER_WIDTH;
rect.bottom = rect.top + HEADER_HEIGHT;
BitBlt( hdc, rect.left, rect.top, HEADER_WIDTH, HEADER_HEIGHT, (SCREEN_MAIN == m_dwScreen) ? m_hdcHeader : m_hdcHeaderSub, 0,0, SRCCOPY );
_InvalidateRectIntl(m_hwnd, &rect, FALSE);
ReleaseDC(m_hwnd, hdc);
}
}
LRESULT CDlgApp::OnMouseMove(int x, int y, DWORD fwKeys)
{
if (GetForegroundWindow() == m_hwnd) // only care if we have focus
{
POINT pt;
pt.x = x;
pt.y = y;
for (int i=0; i<m_DataSrc.m_iItems; i++)
{
HWND hwnd = GetDlgItem(m_hwnd, IDM_MENUITEM0+i);
RECT rect;
rect.left = (i > 0) ? MENUARROWCX(i) : EXITARROWCX(i);
rect.top = (i > 0) ? MENUARROWCY(i) : EXITARROWCY(i);
rect.right = rect.left + MENUICON_WIDTH;
rect.bottom = rect.top + MENUICON_HEIGHT;
if (PtInRect(&rect, pt))
{
SetFocus(GetDlgItem(m_hwnd, IDM_MENUITEM0 + i));
SetCursor(m_hcurHand);
return 0;
}
}
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
return 0;
}
LRESULT CDlgApp::OnLButtonUp(int x, int y, DWORD fwKeys)
{
if (GetForegroundWindow() == m_hwnd) // only care if we have focus
{
POINT pt;
pt.x = x;
pt.y = y;
for (int i=0; i<m_DataSrc.m_iItems; i++)
{
HWND hwnd = GetDlgItem(m_hwnd, IDM_MENUITEM0+i);
RECT rect;
rect.left = (i > 0) ? MENUARROWCX(i) : EXITARROWCX(i);
rect.top = (i > 0) ? MENUARROWCY(i) : EXITARROWCY(i);
rect.right = rect.left + MENUICON_WIDTH;
rect.bottom = rect.top + MENUICON_HEIGHT;
if (PtInRect(&rect, pt))
{
OnCommand(IDM_MENUITEM0 + i);
return 0;
}
}
}
return 0;
}
LRESULT CDlgApp::OnSetCursor(HWND hwnd, int nHittest, int wMouseMsg)
{
if (GetForegroundWindow() == m_hwnd) // only care if we have focus
{
if ( !m_fTaskRunning )
{
if ( hwnd != m_hwnd )
{
SetCursor(m_hcurHand);
return TRUE;
}
}
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
return TRUE;
}
LRESULT CDlgApp::OnChangeScreen(DWORD dwScreen)
{
static DWORD dwSelectedOld; // we store the last position on the main screen
if (m_dwScreen != dwScreen)
{
m_dwScreen = dwScreen;
_RedrawMenu();
_DrawMenuIcons(TRUE);
UpdateWindow(m_hwnd);
_PaintHeaderBitmap();
if (SCREEN_MAIN == dwScreen) // if switching back to main, restore selection
{
m_iSelectedItem = dwSelectedOld;
}
else // otherwise default to the first item in the selection
{
dwSelectedOld = m_iSelectedItem;
m_iSelectedItem = 1;
}
SetFocus(GetDlgItem(m_hwnd, IDM_MENUITEM0 + m_iSelectedItem));
}
return TRUE;
}
LRESULT CDlgApp::OnCommand(int wID)
{
if ( !m_fTaskRunning )
{
int iNewSelectedItem = m_iSelectedItem;
BOOL fRun = FALSE;
switch(wID)
{
case IDM_MENUITEM0:
PostQuitMessage( 0 );
break;
case IDM_MENUITEM1:
case IDM_MENUITEM2:
case IDM_MENUITEM3:
case IDM_MENUITEM4:
case IDM_MENUITEM5:
case IDM_MENUITEM6:
case IDM_MENUITEM7:
fRun = TRUE;
m_iSelectedItem = wID - IDM_MENUITEM0;
// m_iSelectedItem should be a real menu item now, but just to make sure:
ASSERT( (m_iSelectedItem < m_DataSrc.m_iItems) && (m_iSelectedItem >= 0) );
break;
default:
// When we hit this then this isn't a message we care about. We return FALSE which
// tells our WndProc to call DefWndProc which makes everything happy.
return FALSE;
}
if ( fRun )
{
m_fTaskRunning = TRUE;
m_DataSrc.Invoke( m_iSelectedItem, m_hwnd );
m_fTaskRunning = FALSE;
}
}
else
{
// currently the only commands that are valid while another task is running are
// IDM_SHOWCHECK and anything that goes to the default handler above. Everything
// else will come to here and cause a message beep
MessageBeep(0);
}
return TRUE;
}
LRESULT CDlgApp::OnQueryNewPalette()
{
if ( m_hpal )
{
HDC hdc = GetDC(m_hwnd);
if (hdc)
{
HPALETTE hpalOld = SelectPalette(hdc, m_hpal, FALSE);
UnrealizeObject(m_hpal);
RealizePalette(hdc);
UpdateWindow(m_hwnd);
if(hpalOld)
SelectPalette(hdc, hpalOld, FALSE);
ReleaseDC(m_hwnd, hdc);
}
return TRUE;
}
return FALSE;
}
LRESULT CDlgApp::OnPaletteChanged(HWND hwnd)
{
if ( m_hpal && (m_hwnd != hwnd) )
{
HDC hdc = GetDC(m_hwnd);
if (hdc)
{
HPALETTE hpalOld = SelectPalette(hdc, m_hpal, FALSE);
RealizePalette(hdc);
UpdateColors(hdc);
if (hpalOld)
SelectPalette(hdc, hpalOld, FALSE);
ReleaseDC(m_hwnd, hdc);
}
}
return TRUE;
}
LRESULT CDlgApp::OnDrawItem(UINT iCtlID, LPDRAWITEMSTRUCT pdis)
{
int i = iCtlID - IDM_MENUITEM0;
RECT rect = pdis->rcItem;
HPALETTE hpalOld = NULL;
if ( m_hpal )
{
hpalOld = SelectPalette(pdis->hDC, m_hpal, FALSE);
RealizePalette(pdis->hDC);
}
FillRect( pdis->hDC, &rect, (i > 0) ? m_hbrCenterPanel : m_hbrBottomPanel);
if (i < m_DataSrc.m_iItems)
{
SetBkMode(pdis->hDC, TRANSPARENT);
SetTextColor(
pdis->hDC,
((m_DataSrc[i].m_dwFlags&WF_ALTERNATECOLOR)?m_crDisabledText:m_crNormalText));
DrawText(pdis->hDC,m_DataSrc[i].GetTitle(),-1,&rect,DT_NOCLIP|DT_WORDBREAK);
if ( pdis->itemState & ODS_FOCUS )
{
if ( m_fHighContrast )
{
rect.left -= 1;
rect.top -= 2;
rect.right += 1;
rect.bottom -= 2;
DrawFocusRect(pdis->hDC,&rect);
}
}
}
if ( hpalOld )
{
SelectPalette(pdis->hDC, hpalOld, FALSE);
}
_DrawMenuIcons(FALSE);
return TRUE;
}
LRESULT CALLBACK CDlgApp::s_ButtonWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CDlgApp *pThis = (CDlgApp *)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
switch (uMsg)
{
case WM_ERASEBKGND:
return TRUE;
break;
case WM_MOUSEMOVE:
if (GetForegroundWindow() == GetParent(hwnd))
{
if ( !pThis->m_fTaskRunning )
{
int iID = ((int)GetWindowLongPtr(hwnd, GWLP_ID)) - IDM_MENUITEM0;
if ( iID != pThis->m_iSelectedItem )
{
SetFocus(hwnd);
}
}
}
else
{
return FALSE;
}
break;
case WM_SETFOCUS:
if (GetForegroundWindow() == GetParent(hwnd))
{
if ( !pThis->m_fTaskRunning )
{
int iID = ((int)GetWindowLongPtr(hwnd, GWLP_ID)) - IDM_MENUITEM0;
if ( iID != pThis->m_iSelectedItem )
{
pThis->m_iSelectedItem = iID;
SetFocus(GetDlgItem(GetParent(hwnd), IDM_MENUITEM0+iID));
}
}
}
else
{
return FALSE;
}
break;
}
return CallWindowProc(g_fnBtnProc, hwnd, uMsg, wParam, lParam);
}