////////////////////////////////////////////////////////////////////////// // // 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 #include #include // for string compare functions #include #include #include #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 ////////////////////////////////////////////////////////////////////////// typedef DWORD (WINAPI *PFNGETLAYOUT)(HDC); // gdi32!GetLayout typedef DWORD (WINAPI *PFNSETLAYOUT)(HDC, DWORD); // gdi32!SetLayout /** * 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) { // Determine if we should use Direct Animaiton to display our intro graphics. // We don't use DA on slow machines, machines with less than 256 color displays, // and hydra terminals. For everything else we use DA. 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 ); } else { // we must be on NT 4.0 or below. Just assume we aren't in high contrast mode. ASSERT( FALSE == m_fHighContrast ); } // 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; } #define CENTER_RGB_VALUES RGB(90,126,220) #define PANEL_RGB_VALUES RGB(59,52,177) #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) #define DISABLED_RGB_VALUES RGB(128, 128, 128) 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; } BOOL CDlgApp::_CreateFonts(HDC hdc) { #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 // [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++) { memset(&lf,0,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; // TODO: If user has accesibility large fonts turned on then scale the font sizes. LoadStringAuto( m_hInstance, rgFontHeight[m_f8by6 ? 0 : 1][i][RGFONTDEX_FULL], szFontSize, ARRAYSIZE(szFontSize) ); *(rgpcyFont[i]) = MulDiv((_ttoi(szFontSize)), GetDeviceCaps(hdc, LOGPIXELSY), 72); 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]) = MulDiv((_ttoi(szFontSize)), GetDeviceCaps(hdc, LOGPIXELSY), 72); 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 ITEMOFFSET (m_f8by6 ? 35 : 26) #define MENUITEMCX(x) (m_f8by6 ? 270 : 210) #define MENUITEMCY(x) ((m_f8by6 ? 245 : 197) + ((x - 1) * ITEMOFFSET)) #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) * ITEMOFFSET)) #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, MAX_PATH); 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.ShowSplashScreen( 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 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 = 118; } else { rect.left = 77; rect.top = 88; } 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 = 183; } 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 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 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); }