/*--------------------------------------------------------------------------- ** **-------------------------------------------------------------------------*/ #include #include #include "dibutil.h" #include "billbrd.h" #include "animate.h" #ifdef DBG void _BB_Assert(LPCTSTR strFile, unsigned uLine) { TCHAR buf[512]; wsprintf(buf, TEXT("Assertion failed: %s, line %u\n"), strFile, uLine); OutputDebugString(buf); } #endif #define BILLBRD_TEXT_TIMERID 1 #define WHISTLER_PROGRESS_TIMERID 2 // For how long is the text for the Billboard displayed // before switching to the next text #define BB_TEXT_DISPLAY 36000 // For how long is the whistler status move, in millis seconds #define BB_WHISTLER_MOVE 100 // Name to the INI file which discribes the billboards TCHAR g_szFileName[MAX_PATH]; // Path where to find the billboard bitmaps. TCHAR g_szPath[MAX_PATH]; // this application instance HINSTANCE g_hInstance = NULL; // charset properties of font used by this application BYTE g_bCharSet = 0; BOOL g_bBiDi = FALSE; /********************************************************************************** ----------------------------------------------------------------------------------- (LOGO) (banner) ----------------------------------------------------------------------------------- STEP |BILLBRD (GetBBHwd) | | | -----------------------------| ESTIMATE (TimeEstimate) | -----------------------------| PROGRESSTEXT (ProgressText) | -----------------------------| GAUGE (ProgressGauge) | -----------------------------| INFOTEXT (InfoText) | | ----------------------------------------------------------------------------------- (banner) ----------------------------------------------------------------------------------- INFOBAR = STEP, ESTIMATE, GAUGE, PROGRESSTEXT and INFOTEXT NOTE: Position of setup wizard is dependent on the the size and position of BILLBRD. ***********************************************************************************/ UINT g_cyBannerHeight = 0; UINT g_cxLogo = 0; UINT g_cyLogo = 0; UINT g_cxInfoBarWidth = 0; UINT g_cyInfoBarHeight = 0; UINT g_cxSteps = 0; UINT g_cySteps = 0; UINT g_cxStepsWidth = 0; UINT g_cyStepsHeight = 0; UINT g_cxProgressText = 0; UINT g_cyProgressText = 0; UINT g_cxProgressTextWidth = 0; UINT g_cyProgressTextHeight = 0; UINT g_cxGauge = 0; UINT g_cyGauge = 0; UINT g_cxGaugeWidth = 0; UINT g_cyGaugeHeight = 0; UINT g_cxEstimate = 0; UINT g_cyEstimate = 0; UINT g_cxEstimateWidth = 0; UINT g_cyEstimateHeight = 0; UINT g_cxInfoText = 0; UINT g_cyInfoText = 0; UINT g_cxInfoTextWidth = 0; UINT g_cyInfoTextHeight = 0; UINT g_cxBillBrd = 0; UINT g_cyBillBrd = 0; UINT g_cxBillBrdWidth = 0; UINT g_cyBillBrdHeight = 0; UINT g_cxBillBrdHMargin = 0; UINT g_cyBillBrdVMargin = 0; UINT g_cxBillBrdTitleWidth = 0; UINT g_cyBillBrdTitleTop = 0; UINT g_cxBillBrdBodyWidth = 0; HWND g_hwndParent = NULL; // Parent of g_hwnd HWND g_hwnd = NULL; // Parent of all the following windows HWND g_hwndTimeEstimate = NULL; // 'TIMEESTIMATE' HWND g_hwndProgressText = NULL; // 'PROGRESSTEXT' HWND g_hwndProgressGauge= NULL; // 'GAUGE' HWND g_hwndInfoText = NULL; // 'INFOTEXT' HWND g_hwndBB = NULL; // 'BILLBRD' HWND g_hwndSteps = NULL; // 'STEP' HWND g_hwndLogo = NULL; // 'LOGO' HWND g_hwndStatus = NULL; UINT g_idbLogo = 0; UINT g_numBackground = 0; UINT g_idbBackground[3] = {0, 0, 0}; UINT g_idbSelectedBullet = 0; UINT g_idbReleasedBullet = 0; UINT g_idbCurrentBullet = 0; const TCHAR g_cszClassName[] = TEXT("RedCarpetWndClass"); const TCHAR g_szStepsClassName[] = TEXT("InfoStepsWnd_Class"); const TCHAR g_szBillBoardClassName[]= TEXT("BillBoardWnd_Class"); const TCHAR g_szStatusClassName[] = TEXT("BB_WhistlerStatus_Class"); LRESULT CALLBACK RedCarpetWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK BillBoardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK AnimationWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK StatusSubClassWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK ProgressSubClassWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); //---------- // BILLBRD //---------- TCHAR g_szTFont[32]; int g_nTFontHeight; int g_nTFontWidth; int g_nTFontWeight; BOOL g_bTitleShadow = TRUE; TCHAR g_szBFont[32]; int g_nBFontHeight; int g_nBFontWidth; int g_nBFontWeight; BOOL g_bTextShadow = FALSE; int g_nBLineSpace; int g_nAnimID = 0; int g_iCurPanel = -1; // Current billboard to show int g_nPanelCount = 0; // how many billboards are there int g_nLogPixelsY = 1; COLORREF g_colTitle = 0; COLORREF g_colTitleShadow = 0; COLORREF g_colText = 0; COLORREF g_colTextShadow = 0; BB_TEXT bb_text_Personal[] = { {IDS_TITLE1_PER, IDS_TEXT1_PER, IDB_COLL1}, {IDS_TITLE2_PER, IDS_TEXT2_PER, IDB_COLL2}, {IDS_TITLE3_PER, IDS_TEXT3_PER, IDB_COLL2}, {IDS_TITLE4_PER, IDS_TEXT4_PER, IDB_COLL3}, {IDS_TITLE5_PER, IDS_TEXT5_PER, IDB_COLL3}, {IDS_TITLE22_PER, IDS_TEXT22_PER, IDB_COLL10}, {IDS_TITLE6_PER, IDS_TEXT6_PER, IDB_COLL4}, {IDS_TITLE7_PER, IDS_TEXT7_PER, IDB_COLL4}, {IDS_TITLE8_PER, IDS_TEXT8_PER, IDB_COLL5}, {IDS_TITLE9_PER, IDS_TEXT9_PER, IDB_COLL5}, {IDS_TITLE10_PER, IDS_TEXT10_PER, IDB_COLL6}, {IDS_TITLE11_PER, IDS_TEXT11_PER, IDB_COLL6}, {IDS_TITLE12_PER, IDS_TEXT12_PER, IDB_COLL7}, {IDS_TITLE13_PER, IDS_TEXT13_PER, IDB_COLL7}, {IDS_TITLE14_PER, IDS_TEXT14_PER, IDB_COLL8}, {IDS_TITLE15_PER, IDS_TEXT15_PER, IDB_COLL8}, {IDS_TITLE16_PER, IDS_TEXT16_PER, IDB_COLL9}, {IDS_TITLE17_PER, IDS_TEXT17_PER, IDB_COLL9}, {IDS_TITLE18_PER, IDS_TEXT18_PER, IDB_COLL10}, {IDS_TITLE19_PER, IDS_TEXT19_PER, IDB_COLL10}, {IDS_TITLE20_PER, IDS_TEXT20_PER, IDB_COLL10}, {IDS_TITLE21_PER, IDS_TEXT21_PER, IDB_COLL10}, {0,0,0} }; BB_TEXT bb_text_Professional[] = { {IDS_TITLE1, IDS_TEXT1, IDB_COLL1}, {IDS_TITLE2, IDS_TEXT2, IDB_COLL2}, {IDS_TITLE3, IDS_TEXT3, IDB_COLL2}, {IDS_TITLE4, IDS_TEXT4, IDB_COLL3}, {IDS_TITLE5, IDS_TEXT5, IDB_COLL3}, {IDS_TITLE6, IDS_TEXT6, IDB_COLL4}, {IDS_TITLE7, IDS_TEXT7, IDB_COLL4}, {IDS_TITLE8, IDS_TEXT8, IDB_COLL5}, {IDS_TITLE9, IDS_TEXT9, IDB_COLL5}, {IDS_TITLE18, IDS_TEXT18, IDB_COLL9}, {IDS_TITLE10, IDS_TEXT10, IDB_COLL6}, {IDS_TITLE11, IDS_TEXT11, IDB_COLL6}, {IDS_TITLE12, IDS_TEXT12, IDB_COLL7}, {IDS_TITLE13, IDS_TEXT13, IDB_COLL7}, {IDS_TITLE14, IDS_TEXT14, IDB_COLL8}, {IDS_TITLE15, IDS_TEXT15, IDB_COLL8}, {IDS_TITLE16, IDS_TEXT16, IDB_COLL9}, {IDS_TITLE17, IDS_TEXT17, IDB_COLL9}, {0,0,0} }; BB_TEXT bb_text_Blade[] = { {IDS_TITLE1_S, IDS_TEXT1_S, IDB_COLL1}, {IDS_TITLE2_S, IDS_TEXT2_S, IDB_COLL2}, {IDS_TITLE3_S, IDS_TEXT3_S, IDB_COLL2}, {IDS_TITLE4_S, IDS_TEXT4_S, IDB_COLL3}, {IDS_TITLE5_S, IDS_TEXT5_S, IDB_COLL3}, {IDS_TITLE6_S, IDS_TEXT6_S, IDB_COLL4}, {IDS_TITLE7_S, IDS_TEXT7_S, IDB_COLL4}, {IDS_TITLE8_S, IDS_TEXT8_S, IDB_COLL5}, {IDS_TITLE9_S, IDS_TEXT9_S, IDB_COLL5}, {IDS_TITLE10_S, IDS_TEXT10_S, IDB_COLL6}, {0,0,0} }; BB_TEXT bb_text_SmallBusiness[] = { {IDS_TITLE1_S, IDS_TEXT1_S, IDB_COLL1}, {IDS_TITLE3_S, IDS_TEXT3_S, IDB_COLL2}, {IDS_TITLE4_S, IDS_TEXT4_S, IDB_COLL3}, {IDS_TITLE5_S, IDS_TEXT5_S, IDB_COLL3}, {IDS_TITLE6_S, IDS_TEXT6_S, IDB_COLL4}, {IDS_TITLE7_S, IDS_TEXT7_S, IDB_COLL4}, {IDS_TITLE8_S, IDS_TEXT8_S, IDB_COLL5}, {IDS_TITLE9_S, IDS_TEXT9_S, IDB_COLL5}, {IDS_TITLE10_S, IDS_TEXT10_S, IDB_COLL6}, {0,0,0} }; BB_TEXT bb_text_Server[] = { {IDS_TITLE1_S, IDS_TEXT1_S, IDB_COLL1}, {IDS_TITLE2_S, IDS_TEXT2_S, IDB_COLL2}, {IDS_TITLE3_S, IDS_TEXT3_S, IDB_COLL2}, {IDS_TITLE4_S, IDS_TEXT4_S, IDB_COLL3}, {IDS_TITLE5_S, IDS_TEXT5_S, IDB_COLL3}, {IDS_TITLE6_S, IDS_TEXT6_S, IDB_COLL4}, {IDS_TITLE7_S, IDS_TEXT7_S, IDB_COLL4}, {IDS_TITLE8_S, IDS_TEXT8_S, IDB_COLL5}, {IDS_TITLE9_S, IDS_TEXT9_S, IDB_COLL5}, {IDS_TITLE10_S, IDS_TEXT10_S, IDB_COLL6}, {0,0,0} }; BB_TEXT bb_text_AdvancedServer[] = { {IDS_TITLE1_S, IDS_TEXT1_S, IDB_COLL1}, {IDS_TITLE2_S, IDS_TEXT2_S, IDB_COLL2}, {IDS_TITLE3_S, IDS_TEXT3_S, IDB_COLL2}, {IDS_TITLE4_S, IDS_TEXT4_S, IDB_COLL3}, {IDS_TITLE5_S, IDS_TEXT5_S, IDB_COLL3}, {IDS_TITLE6_S, IDS_TEXT6_S, IDB_COLL4}, {IDS_TITLE7_S, IDS_TEXT7_S, IDB_COLL4}, {IDS_TITLE8_S, IDS_TEXT8_S, IDB_COLL5}, {IDS_TITLE9_S, IDS_TEXT9_S, IDB_COLL5}, {IDS_TITLE10_S, IDS_TEXT10_S, IDB_COLL6}, {0,0,0} }; BB_TEXT bb_text_DataCenter[] = { {IDS_TITLE1_S, IDS_TEXT1_S, IDB_COLL1}, {IDS_TITLE2_S, IDS_TEXT2_S, IDB_COLL2}, {IDS_TITLE3_S, IDS_TEXT3_S, IDB_COLL2}, {IDS_TITLE4_S, IDS_TEXT4_S, IDB_COLL3}, {IDS_TITLE5_S, IDS_TEXT5_S, IDB_COLL3}, {IDS_TITLE6_S, IDS_TEXT6_S, IDB_COLL4}, {IDS_TITLE7_S, IDS_TEXT7_S, IDB_COLL4}, {IDS_TITLE8_S, IDS_TEXT8_S, IDB_COLL5}, {IDS_TITLE9_S, IDS_TEXT9_S, IDB_COLL5}, {IDS_TITLE10_S, IDS_TEXT10_S, IDB_COLL6}, {0,0,0} }; BB_TEXT bb_text_Professional_IA64[] = { {IDS_TITLE1_64PRO, IDS_TEXT1_64PRO, IDB_COLL1}, {IDS_TITLE2_64PRO, IDS_TEXT2_64PRO, IDB_COLL2}, {IDS_TITLE3_64PRO, IDS_TEXT3_64PRO, IDB_COLL2}, {IDS_TITLE4_64PRO, IDS_TEXT4_64PRO, IDB_COLL3}, {IDS_TITLE5_64PRO, IDS_TEXT5_64PRO, IDB_COLL3}, {IDS_TITLE6_64PRO, IDS_TEXT6_64PRO, IDB_COLL4}, {IDS_TITLE7_64PRO, IDS_TEXT7_64PRO, IDB_COLL4}, {IDS_TITLE8_64PRO, IDS_TEXT8_64PRO, IDB_COLL5}, {IDS_TITLE9_64PRO, IDS_TEXT9_64PRO, IDB_COLL5}, {IDS_TITLE10_64PRO, IDS_TEXT10_64PRO, IDB_COLL6}, {IDS_TITLE11_64PRO, IDS_TEXT11_64PRO, IDB_COLL6}, {IDS_TITLE12_64PRO, IDS_TEXT12_64PRO, IDB_COLL7}, {IDS_TITLE13_64PRO, IDS_TEXT13_64PRO, IDB_COLL7}, {0,0,0} }; // 0 - professional, // 1 - Server, // 2 - Advanced Server, // 3 - Data Center, // 4 - for personal // 5 - for Blade // 6 - for SmallBusiness DWORD dwBBTextType = 0; // Be careful with this order. It has to be the same as // *_PRODUCTTYPE in winnt32.h #ifdef _X86_ BB_TEXT* bb_text[] = { bb_text_Professional, bb_text_Server, bb_text_AdvancedServer, bb_text_DataCenter, bb_text_Personal, bb_text_Blade, bb_text_SmallBusiness}; #else BB_TEXT* bb_text[] = { bb_text_Professional_IA64, bb_text_Server, bb_text_AdvancedServer, bb_text_DataCenter, bb_text_Personal }; #endif HDC g_hdcBbMem = NULL; HBITMAP g_hbmpBbMemOld = NULL; HDC GetBillboardBuffer(); BOOL BufferBillboard( IN HWND hwnd, IN HDC hdc ); VOID DestroyBillboardBuffer(); //--------- // INFOBAR //--------- COLORREF g_colInfoText = 0; COLORREF g_colStepsTxt = 0; COLORREF g_colStepsMarkTxt = 0; COLORREF g_colStepsCurrentTxt = 0; COLORREF g_colStepsTitle = 0; COLORREF g_colGaugeBg = 0; COLORREF g_colGauge = 0; COLORREF g_colBulletTrans = 0; //------------- // TIMEESTIMATE //------------- // Original position of the progress text window // Since we want the text adjusted to the bottom of the window // we resize the window as needed, but should not grow it // beyond the original size. RECT g_rcProgressText; //----- // LOGO //----- HBITMAP g_hbmWinLogo = NULL; COLORREF g_colLogoTransparency = RGB(0, 0, 0); COLORREF g_colStatusTransperency = RGB(0, 0, 0); //----------- // background //----------- HDC g_hdcMem = NULL; HBITMAP g_hbmpMemOld = NULL; INT g_iStretchMode = STRETCH_ANDSCANS; BOOL BufferBackground( IN HWND hwnd ); LRESULT OnEraseBkgnd( HWND hwnd, WPARAM wParam, LPARAM lParam ); VOID DestroyBackgroundBuffer(); HBITMAP MyLoadImage( IN HDC hdc, IN UINT* idbBackground, IN int iNumImage ); void SetFontCharSet(void) { HFONT hFont = NULL; LOGFONT lf; //init font charset hFont = GetStockObject(SYSTEM_FONT); if(hFont) { if(GetObject(hFont, sizeof(lf), &lf)) g_bCharSet = lf.lfCharSet; DeleteObject(hFont); } } void SetFontColor(HWND hwnd) { HDC hdc; UINT uiBitsPixel; hdc = GetDC(hwnd); uiBitsPixel = (UINT) GetDeviceCaps(hdc, BITSPIXEL); if (uiBitsPixel > 8) { g_colTitle = COLOR_TITLE_C16BIT; g_colTitleShadow = COLOR_SHADOW_C16BIT; g_colText = COLOR_TEXT_C16BIT; g_colTextShadow = COLOR_SHADOW_C16BIT; g_colInfoText = UI_INFOTEXT_COLOR_C16BIT; g_colStepsTxt = UI_STEPSTEXT_COLOR_C16BIT; g_colStepsMarkTxt = UI_STEPSTEXT_MARK_COLOR_C16BIT; g_colStepsCurrentTxt = UI_STEPSTEXT_CURRENT_COLOR_C16BIT; g_colStepsTitle = UI_STEPSTITLE_COLOR_C16BIT; g_colGaugeBg = UI_GAUGE_BACKGROUND_COLOR_C16BIT; g_colGauge = UI_GAUGE_COLOR_C16BIT; g_colStatusTransperency = UI_STATUS_TRANSPARENT_COLOR_C16BIT; g_colLogoTransparency = UI_LOGO_TRANSPARENT_COLOR_C16BIT; g_colBulletTrans = UI_BULLET_TRANPARENT_COLOR_C16BIT; } else { g_colTitle = COLOR_TITLE_C4BIT; g_colTitleShadow = COLOR_SHADOW_C4BIT; g_colText = COLOR_TEXT_C4BIT; g_colTextShadow = COLOR_SHADOW_C4BIT; g_colInfoText = UI_INFOTEXT_COLOR_C4BIT; g_colStepsTxt = UI_STEPSTEXT_COLOR_C4BIT; g_colStepsCurrentTxt = UI_STEPSTEXT_CURRENT_COLOR_C4BIT; g_colStepsMarkTxt = UI_STEPSTEXT_MARK_COLOR_C4BIT; g_colStepsTitle = UI_STEPSTITLE_COLOR_C4BIT; g_colGaugeBg = UI_GAUGE_BACKGROUND_COLOR_C4BIT; g_colGauge = UI_GAUGE_COLOR_C4BIT; g_colStatusTransperency = UI_STATUS_TRANSPARENT_COLOR_C4BIT; g_colLogoTransparency = UI_LOGO_TRANSPARENT_COLOR_C4BIT; g_colBulletTrans = UI_BULLET_TRANPARENT_COLOR_C4BIT; } ReleaseDC(hwnd, hdc); } typedef struct _RES_FONTSIZES { UINT uiID; UINT uiDefault; } RES_FONTSIZES; RES_FONTSIZES res_1024[] = { {IDS_TITLEFONTSIZE_1024, 24}, {IDS_TITLEFONTWIDTH_1024, 0}, {IDS_TEXTFONTSIZE_1024, 11}, {IDS_TEXTFONTWIDTH_1024, 0} }; RES_FONTSIZES res_800[] = { {IDS_TITLEFONTSIZE_800, 21}, {IDS_TITLEFONTWIDTH_800, 0}, {IDS_TEXTFONTSIZE_800, 10}, {IDS_TEXTFONTWIDTH_800, 0} }; RES_FONTSIZES res_640[] = { {IDS_TITLEFONTSIZE_640, 18}, {IDS_TITLEFONTWIDTH_640, 0}, {IDS_TEXTFONTSIZE_640, 9}, {IDS_TEXTFONTWIDTH_640, 0} }; void GetMyFontsFromFile() { RECT rc; int iSize = 0; TCHAR szBuf[25]; RES_FONTSIZES *pres_fontsize = NULL; iSize = GetSystemMetrics(SM_CXSCREEN); if (iSize >= 1024) { pres_fontsize = res_1024; } else if (iSize == 800) { pres_fontsize = res_800; } else { pres_fontsize = res_640; } if (LoadString(g_hInstance, pres_fontsize[0].uiID, (LPTSTR)szBuf, sizeof(szBuf)/sizeof(TCHAR))) g_nTFontHeight = MyAtoI((const TCHAR*)szBuf); else g_nTFontHeight = pres_fontsize[0].uiDefault; if (LoadString(g_hInstance, pres_fontsize[1].uiID, (LPTSTR)szBuf, sizeof(szBuf)/sizeof(TCHAR))) g_nTFontWidth = MyAtoI((const TCHAR*)szBuf); else g_nTFontWidth = pres_fontsize[1].uiDefault; if (LoadString(g_hInstance, pres_fontsize[2].uiID, (LPTSTR)szBuf, sizeof(szBuf)/sizeof(TCHAR))) g_nBFontHeight = MyAtoI((const TCHAR*)szBuf); else g_nBFontHeight = pres_fontsize[2].uiDefault; if (LoadString(g_hInstance, pres_fontsize[3].uiID, (LPTSTR)szBuf, sizeof(szBuf)/sizeof(TCHAR))) g_nBFontWidth = MyAtoI((const TCHAR*)szBuf); else g_nBFontWidth = pres_fontsize[3].uiDefault; if (!(LoadString(g_hInstance, IDS_TITLEFONTNAME, (LPTSTR)g_szTFont, sizeof(g_szTFont)/sizeof(TCHAR)))) lstrcpy(g_szTFont, TEXT("Arial")); if (LoadString(g_hInstance, IDD_TITLEFONTWEIGHT, (LPTSTR)szBuf, sizeof(szBuf)/sizeof(TCHAR))) g_nTFontWeight = MyAtoI((const TCHAR*)szBuf); else g_nTFontWeight = FW_BOLD; if (!(LoadString(g_hInstance, IDS_TEXTFONTNAME, (LPTSTR)g_szBFont, sizeof(g_szBFont)/sizeof(TCHAR)))) lstrcpy(g_szBFont, TEXT("Arial")); if (LoadString(g_hInstance, IDD_TEXTFONTWEIGHT, (LPTSTR)szBuf, sizeof(szBuf)/sizeof(TCHAR))) g_nBFontWeight = MyAtoI((const TCHAR*)szBuf); else g_nBFontWeight = FW_BOLD; if (LoadString(g_hInstance, IDD_BIDI, (LPTSTR)szBuf, sizeof(szBuf)/sizeof(TCHAR))) g_bBiDi = (0 != MyAtoI((const TCHAR*)szBuf)); else g_bBiDi = FALSE; if (LoadString(g_hInstance, IDS_TEXTFONT_LINESPACING, (LPTSTR)szBuf, sizeof(szBuf)/sizeof(TCHAR))) g_nBLineSpace = MyAtoI((const TCHAR*)szBuf); else g_nBLineSpace = 0; return; } void GetMyImagesFromFile(HWND hwnd) { HDC hdc; UINT cxScreen; UINT uiBitsPixel; cxScreen = (UINT) GetSystemMetrics(SM_CXSCREEN); hdc = GetDC(hwnd); if (hdc != NULL) { uiBitsPixel = (UINT) GetDeviceCaps(hdc, BITSPIXEL); ReleaseDC(hwnd, hdc); } else { uiBitsPixel = 4; } if (uiBitsPixel > 8) { g_numBackground = 1; g_iStretchMode = STRETCH_DELETESCANS; if ((dwBBTextType == 0) || (dwBBTextType == 4)) { g_idbBackground[0] = IDB_BACKGROUND_C16BIT; g_idbSelectedBullet = IDB_SELECTEDBULLET_C16BIT; g_idbReleasedBullet = IDB_RELEASEDBULLET_C16BIT; g_idbCurrentBullet = IDB_CURRENTBULLET_C16BIT; if (cxScreen >= 1024) g_idbLogo = IDB_LOGO1024_C16BIT; else if (cxScreen >= 800) g_idbLogo = IDB_LOGO800_C16BIT; else g_idbLogo = IDB_LOGO640_C16BIT; } else { g_idbBackground[0] = IDB_SRV_BACKGROUND_C16BIT; g_idbSelectedBullet = IDB_SRV_SELECTEDBULLET_C16BIT; g_idbReleasedBullet = IDB_SRV_RELEASEDBULLET_C16BIT; g_idbCurrentBullet = IDB_SRV_CURRENTBULLET_C16BIT; if (cxScreen >= 1024) g_idbLogo = IDB_SRV_LOGO1024_C16BIT; else if (cxScreen >= 800) g_idbLogo = IDB_SRV_LOGO800_C16BIT; else g_idbLogo = IDB_SRV_LOGO640_C16BIT; } } else { g_numBackground = 1; g_iStretchMode = STRETCH_ANDSCANS; if ((dwBBTextType == 0) || (dwBBTextType == 4)) { g_idbBackground[0] = IDB_BACKGROUND_C4BIT; g_idbSelectedBullet = IDB_SELECTEDBULLET_C4BIT; g_idbReleasedBullet = IDB_RELEASEDBULLET_C4BIT; g_idbCurrentBullet = IDB_CURRENTBULLET_C4BIT; if (cxScreen >= 1024) g_idbLogo = IDB_LOGO1024_C4BIT; else if (cxScreen >= 800) g_idbLogo = IDB_LOGO800_C4BIT; else g_idbLogo = IDB_LOGO640_C4BIT; } else { g_idbBackground[0] = IDB_SRV_BACKGROUND_C4BIT; g_idbSelectedBullet = IDB_SRV_SELECTEDBULLET_C4BIT; g_idbReleasedBullet = IDB_SRV_RELEASEDBULLET_C4BIT; g_idbCurrentBullet = IDB_SRV_CURRENTBULLET_C4BIT; if (cxScreen >= 1024) g_idbLogo = IDB_SRV_LOGO1024_C4BIT; else if (cxScreen >= 800) g_idbLogo = IDB_SRV_LOGO800_C4BIT; else g_idbLogo = IDB_SRV_LOGO640_C4BIT; } } } /**************************************************************************** * SetLayoutParams() * * Set all the layout parameter for Billboard. All the floating point numbers * come the design specification. This function uses the values of * g_nBFontHeight and g_nTFontHeight. * NOTE: Call this function again and MoveWindow afterward, in case of * resolution changes * *****************************************************************************/ void SetLayoutParams() { int cxScreen; int cyScreen; int iCommentLeft; int iCommonWidth; int iFontHeight; RECT rcSteps; UINT cySteps; cxScreen = GetSystemMetrics(SM_CXSCREEN); cyScreen = GetSystemMetrics(SM_CYSCREEN); iFontHeight = abs(GetInfoBarFontHeight()); g_cyBannerHeight = cyScreen * 13 / 200; g_cxLogo = (UINT) (cxScreen * 0.0195); g_cyLogo = (UINT) (cyScreen * 0.0053); g_cxInfoBarWidth = (cxScreen) * 28 / 100; g_cyInfoBarHeight = (cyScreen) - g_cyBannerHeight * 2; if (cxScreen < 800) { rcSteps.left = g_cxInfoBarWidth * 3 / 20; rcSteps.top = g_cyBannerHeight * 2; rcSteps.right = g_cxInfoBarWidth - rcSteps.left; // Use 1.5 line height and reserve 2 lines for each step text, hence 7 / 2 rcSteps.bottom = rcSteps.top + (iFontHeight * 7 / 2) * (UI_INFOBAR_NUM_STEPS) + (UINT) ((0.068) * cyScreen); iCommentLeft = rcSteps.left; iCommonWidth = g_cxInfoBarWidth - 2 * rcSteps.left; } else { rcSteps.left = (UINT) (0.039 * cxScreen); rcSteps.top = (UINT) (0.059 * cyScreen) + g_cyBannerHeight + g_nTFontHeight + g_nBFontHeight; rcSteps.right = rcSteps.left + (UINT) (0.2005 * cxScreen); // Use 1.5 line height and reserve 1 line for each step text, hence 5 / 2 rcSteps.bottom = rcSteps.top + (iFontHeight * 5 / 2) * (UI_INFOBAR_NUM_STEPS) + (UINT) ((0.068) * cyScreen); iCommentLeft = rcSteps.left; iCommonWidth = (UINT) (0.1705 * cxScreen); } if (GetStepsHeight(g_cxInfoBarWidth, cyScreen, rcSteps, &cySteps)) { rcSteps.bottom = cySteps; } g_cxSteps = rcSteps.left; g_cySteps = rcSteps.top; g_cxStepsWidth = rcSteps.right - rcSteps.left; g_cyStepsHeight = rcSteps.bottom - rcSteps.top; g_cxEstimate = iCommentLeft; if (cxScreen < 800) { g_cyEstimate = g_cyStepsHeight + g_cySteps + 3 * iFontHeight / 2; } else { g_cyEstimate = g_cyStepsHeight + g_cySteps + (UINT) (0.063 * cyScreen); } g_cxEstimateWidth = iCommonWidth; g_cyEstimateHeight = iFontHeight * 5; g_cxProgressText = iCommentLeft; g_cyProgressText = g_cyEstimateHeight + g_cyEstimate; g_cxProgressTextWidth = iCommonWidth; g_cyProgressTextHeight = iFontHeight * 3; g_cxGauge = iCommentLeft; g_cyGauge = g_cyProgressTextHeight + g_cyProgressText + iFontHeight / 3; g_cxGaugeWidth = iCommonWidth; g_cyGaugeHeight = iFontHeight * 3 / 2; g_cxInfoText = iCommentLeft; if (cxScreen < 800) { g_cyInfoText = g_cyGauge + g_cyGaugeHeight + iFontHeight; g_cyInfoTextHeight = cyScreen - g_cyInfoText - g_cyBannerHeight; } else { g_cyInfoTextHeight = (cyScreen - g_cyGaugeHeight - iFontHeight / 3 - g_cyGauge - g_cyBannerHeight) * 2 / 3 + iFontHeight; g_cyInfoText = cyScreen - g_cyBannerHeight - g_cyInfoTextHeight; } g_cxInfoTextWidth = iCommonWidth; if (g_bBiDi) { // mirroring along the center of infobar. int shiftAmt = g_cxInfoBarWidth - 2 * g_cxEstimate - g_cxEstimateWidth; if (shiftAmt < 0) { shiftAmt = 0; } g_cxSteps = g_cxInfoBarWidth - g_cxSteps - g_cxStepsWidth - shiftAmt; g_cxEstimate = g_cxInfoBarWidth - g_cxEstimate - g_cxEstimateWidth - shiftAmt; g_cxProgressText = g_cxInfoBarWidth - g_cxProgressText - g_cxProgressTextWidth - shiftAmt; g_cxGauge = g_cxInfoBarWidth - g_cxGauge - g_cxGaugeWidth - shiftAmt; g_cxInfoText = g_cxInfoBarWidth - g_cxInfoText - g_cxInfoTextWidth - shiftAmt; } g_cxBillBrd = g_cxInfoBarWidth; g_cyBillBrd = g_cyBannerHeight; g_cxBillBrdWidth = cxScreen - g_cxBillBrd; g_cyBillBrdHeight = g_cyInfoBarHeight; g_cxBillBrdHMargin = (UINT) (cxScreen * 0.06); g_cyBillBrdVMargin = 0; // Only substract 2*margin for the area for the billboard title // otherwise the new text does not fit on 640x480 g_cxBillBrdTitleWidth = g_cxBillBrdWidth - (2 * g_cxBillBrdHMargin); g_cyBillBrdTitleTop = g_cySteps - g_cyBillBrd; // Only substract 2*margin for the area for the billboard text // otherwise the new text does not fit on 640x480 g_cxBillBrdBodyWidth = g_cxBillBrdWidth - (2 * g_cxBillBrdHMargin); } HDC GetBackgroundBuffer() { return g_hdcMem; } VOID DestroyBackgroundBuffer() { HBITMAP hbmpMem; hbmpMem = SelectObject(g_hdcMem, g_hbmpMemOld); if (hbmpMem) { DeleteObject(hbmpMem); } g_hbmpMemOld = NULL; DeleteDC(g_hdcMem); g_hdcMem = NULL; } BOOL StretchBitmapAndDisplay( HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD fdwRop ) /*++ Routine Description: This function takes a bitmap that needs to be displayed and stretches it using GDI. Once the bitmap is stretched to the required dimentions we display it using BitBlt. We have to do this decause some buggy video drivers and or hardware hang on using StretchBlt. Or the StretchBlt would generate a corupted bitmap. Arguments: hdcDest destination device-context handle nXOriginDest x-coordinate of origin of destination rectangle nYOriginDest y-coordinate of origin of destination rectangle nWidthDest width of destination rectangle nHeightDest height of destination rectangle hdcSrc source device-context handle nXOriginSrc x-coordinate of origin of source rectangle nYOriginSrc y-coordinate of origin of source rectangle nWidthSrc width of source rectangle nHeightSrc height of source rectangle fdwRop raster operation Return value: TRUE == SUCCESS Changes: 10/11/97 hanumany Created 04/30/01 chunhoc Modified --*/ { HDC hdcTemp = NULL; BOOL bRet = FALSE; int iOldStretchMode = 0; HBITMAP hBmp = NULL; HBITMAP hBmpOld = NULL; UINT uiNumColors = 0; //Create the temp DC hdcTemp = CreateCompatibleDC(hdcDest); //Create a bitmap hBmp = CreateCompatibleBitmap(hdcSrc, nWidthDest, nHeightDest); if(hdcTemp && hBmp) { // Select it into the temp DC hBmpOld = SelectObject(hdcTemp, hBmp); //set stretch blt mode iOldStretchMode = SetStretchBltMode(hdcTemp, g_iStretchMode); //StretchBlt bRet = StretchBlt(hdcTemp, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, fdwRop); // restore the old stretch mode SetStretchBltMode(hdcTemp, iOldStretchMode); if(bRet) { //We succeeded in stretching the bitmap on the temp DC. Now lets BitBlt it. bRet = BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcTemp, 0, 0, SRCCOPY); } } //CleanUp if(hBmpOld) { SelectObject(hdcTemp, hBmpOld); } if(hBmp) { DeleteObject(hBmp); } if(hdcTemp) { DeleteDC(hdcTemp); } return bRet; } BOOL BufferBackground( IN HWND hwnd ) /*++ Routine Description: Create a memory buffer for the stretched bitmap to improve performance. Arguments: hwnd - Handle to the window on which the background bitmap is drawn Return Value: TRUE - if the buffered background image is created successfully FALSE - otherwise g_hdcMem - The memory DC to receive the buffered bitmap if succeeeds, NULL if fails. g_hbmpMemOld - Save the old memory buffer of g_hdcMem --*/ { BOOL bRet = FALSE; HDC hdcMem = NULL; HBITMAP hbmpMemOld= NULL; HBITMAP hbmpMem = NULL; HDC hdc = NULL; HDC hdcImgSrc = NULL; BITMAP bm; HBITMAP hbmBackground = NULL; HBITMAP hBitmapOld = NULL; RECT rcBackground; if (!GetClientRect(hwnd, &rcBackground)) { goto cleanup; } hdc = GetDC(hwnd); if (!hdc) { goto cleanup; } hbmpMem = CreateCompatibleBitmap(hdc, rcBackground.right - rcBackground.left, rcBackground.bottom - rcBackground.top); hdcMem = CreateCompatibleDC(hdc); if (!hdcMem || !hbmpMem) { goto cleanup; } hbmpMemOld = SelectObject(hdcMem, hbmpMem); if (g_numBackground > 1) { hbmBackground = MyLoadImage(hdc, g_idbBackground, g_numBackground); } else { hbmBackground = (HBITMAP) LoadImage(g_hInstance, MAKEINTRESOURCE(g_idbBackground[0]), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE); } hdcImgSrc = CreateCompatibleDC(hdc); if (!hbmBackground || !hdcImgSrc) { goto cleanup; } hBitmapOld = (HBITMAP) SelectObject(hdcImgSrc, hbmBackground); GetObject(hbmBackground , sizeof(BITMAP), &bm); bRet = StretchBitmapAndDisplay(hdcMem, 0, 0, rcBackground.right - rcBackground.left, rcBackground.bottom - rcBackground.top, hdcImgSrc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); SelectObject(hdcImgSrc, hBitmapOld); if (bRet) { g_hdcMem = hdcMem; g_hbmpMemOld = hbmpMemOld; hdcMem = NULL; hbmpMemOld = NULL; hbmpMem = NULL; } cleanup: if (hdcImgSrc) { DeleteDC(hdcImgSrc); } if (hbmBackground) { DeleteObject(hbmBackground); } if (hbmpMemOld != NULL) { SelectObject(hdcMem, hbmpMemOld); } if (hbmpMem != NULL) { DeleteObject(hbmpMem); } if (hdcMem != NULL) { DeleteDC(hdcMem); } if (hdc) { ReleaseDC(hwnd, hdc); } return bRet; } LRESULT OnEraseBkgnd( HWND hwnd, WPARAM wParam, LPARAM lParam ) /*++ Routine Description: Handle the WM_ERASEBKGND for the child windows of the main window, RedCarpetWndClass Arguments: hwnd - hwnd to a child window of RedCarpetWndClass wParam - same as the wParam pass to WM_ERASEBKGND (see MSDN) lParam - same as the lParam pass to WM_ERASEBKGND (see MSDN) Return Value: 1 if the background is erased successfully, 0 otherwise. (see MSDN) --*/ { LRESULT lRet = 0; RECT rc; RECT rcToParent; if (GetClientRect(hwnd, &rc)) { HDC hdc = (HDC) wParam; HDC hdcMem; hdcMem = GetBackgroundBuffer(); GetRectInParent(hwnd, &rc, &rcToParent); lRet = (LRESULT) BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdcMem, rcToParent.left, rcToParent.top, SRCCOPY); } return lRet; } HDC GetBillboardBuffer() { return g_hdcBbMem; } VOID DestroyBillboardBuffer() { HBITMAP hbmpMem; hbmpMem = SelectObject(g_hdcBbMem, g_hbmpBbMemOld); if (hbmpMem) { DeleteObject(hbmpMem); } g_hbmpBbMemOld = NULL; DeleteDC(g_hdcBbMem); g_hdcBbMem = NULL; } HBITMAP MyLoadImage( IN HDC hdc, IN UINT* idbBackground, IN int iNumImage ) /*++ Routine Description: OR all the specified bitmaps in the resource file and return the result image handle. This is particularly useful when we want to use RLE on a 16 or 24-bit bitmap, because DIB format only permits RLE of 4bpp or 8bpp bitmap. Arguments: hdc - a device context idbBackground - list of bitmap resource id's iNumImage - number of id in idbBackground Return Values: the result image handle on success; NULL on failure Note: Assume all the bitmaps have the same dimension. --*/ { HBITMAP hbmBackground[] = {NULL, NULL, NULL}; HBITMAP hbmpImgSrcOld = NULL; HDC hdcImgSrc = NULL; HBITMAP hbmpMem = NULL; HBITMAP hbmpMemOld = NULL; HDC hdcMem = NULL; HBITMAP hbmpRet = NULL; DWORD dwRop; int i; BITMAP bm; for (i = 0; i < iNumImage; i++) { hbmBackground[i] = (HBITMAP) LoadImage(g_hInstance, MAKEINTRESOURCE(idbBackground[i]), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE); if (hbmBackground[i] == NULL) { goto cleanup; } } hdcImgSrc = CreateCompatibleDC(hdc); if (hdcImgSrc == NULL) { goto cleanup; } if (!GetObject(hbmBackground[0], sizeof(BITMAP), &bm)) { goto cleanup; } hbmpMem = CreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight); hdcMem = CreateCompatibleDC(hdc); if (!hdcMem || !hbmpMem) { goto cleanup; } i = 0; dwRop = SRCCOPY; hbmpMemOld = SelectObject(hdcMem, hbmpMem); hbmpImgSrcOld = (HBITMAP) SelectObject(hdcImgSrc, hbmBackground[i]); while (TRUE) { if (!BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcImgSrc, 0, 0, dwRop)) { goto cleanup; } i++; if (i >= iNumImage) { break; } dwRop = SRCPAINT; SelectObject(hdcImgSrc, hbmBackground[i]); } hbmpRet = hbmpMem; hbmpMem = NULL; cleanup: if (hbmpImgSrcOld) { SelectObject(hdcImgSrc, hbmpImgSrcOld); } if (hbmpMemOld) { SelectObject(hdcMem, hbmpMemOld); } if (hdcMem) { DeleteDC(hdcMem); } if (hbmpMem) { DeleteObject(hbmpMem); } if (hdcImgSrc) { DeleteDC(hdcImgSrc); } for (i = 0; i < iNumImage; i++) { if (hbmBackground[i]) { DeleteObject(hbmBackground[i]); } } return hbmpRet; } BOOL BufferBillboard( IN HWND hwnd, IN HDC hdc ) /*++ Routine Description: Create a memory buffer for the billboard. Arguments: hwnd - Handle to the window on which the Billboard bitmap is drawn hdc - Handle to the screen DC of billboard Return Value: TRUE - if the buffered background image is created successfully FALSE - otherwise g_hdcBbMem - The memory DC to receive the buffered bitmap if succeeeds, NULL if fails. g_hbmpBbMem - Save the old memory buffer of g_hdcBbMem --*/ { BOOL bRet = FALSE; HDC hdcMem = NULL; HBITMAP hbmpMem = NULL; RECT rcBillboard; if (!GetClientRect(hwnd, &rcBillboard)) { goto cleanup; } hbmpMem = CreateCompatibleBitmap(hdc, rcBillboard.right - rcBillboard.left, rcBillboard.bottom - rcBillboard.top); hdcMem = CreateCompatibleDC(hdc); if (!hdcMem || !hbmpMem) { goto cleanup; } g_hbmpBbMemOld = SelectObject(hdcMem, hbmpMem); Animate(hdcMem); bRet = TRUE; g_hdcBbMem = hdcMem; hdcMem = NULL; hbmpMem = NULL; cleanup: if (hbmpMem != NULL) { SelectObject(hdcMem, g_hbmpBbMemOld); DeleteObject(hbmpMem); g_hbmpBbMemOld = NULL; } if (hdcMem != NULL) { DeleteDC(hdcMem); } return bRet; } /***************************************************************************** * * GetRectInParent(hwndChild, prcClip, pRect) * * This function gets the rect of child window relative to the client * coordinate of the parent * ******************************************************************************/ void GetRectInParent(HWND hwndChild, LPRECT prcClip, LPRECT pRect) { RECT rcChild; POINT ptChild; HWND hwnd; hwnd = GetParent(hwndChild); if (hwnd == NULL) { hwnd = hwndChild; } if ( prcClip == NULL ) { GetClientRect( hwndChild, &rcChild ); } else { rcChild = *prcClip; } ptChild.x = rcChild.left; ptChild.y = rcChild.top; ClientToScreen( hwndChild, &ptChild ); ScreenToClient( hwnd, &ptChild ); pRect->left = ptChild.x; pRect->top = ptChild.y; ptChild.x = rcChild.right; ptChild.y = rcChild.bottom; ClientToScreen( hwndChild, &ptChild ); ScreenToClient( hwnd, &ptChild ); pRect->right = ptChild.x; pRect->bottom = ptChild.y; } BOOL WINAPI InitRealBillBoard(HWND hwndParent) { WNDCLASS wc; RECT rc1; wc.style = (UINT)CS_BYTEALIGNWINDOW; wc.lpfnWndProc = BillBoardWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = g_szBillBoardClassName; if (!RegisterClass (&wc)) return FALSE; GetWindowRect(hwndParent, &rc1); rc1.left = rc1.left + g_cxBillBrd; rc1.top = rc1.top + g_cyBillBrd; rc1.bottom = rc1.top + g_cyBillBrdHeight; g_hwndBB = CreateWindow( g_szBillBoardClassName, TEXT(""), WS_CHILD, rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top, hwndParent, NULL, g_hInstance, NULL); if (g_hwndBB == NULL) { UnregisterClass(g_szBillBoardClassName, g_hInstance); return FALSE; } ShowWindow( g_hwndBB, SW_HIDE ); return TRUE; } BOOL WINAPI InitStatus(HWND hwndParent) { WNDCLASS wc; RECT rc1; wc.style = (UINT)CS_BYTEALIGNWINDOW; wc.lpfnWndProc = AnimationWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = g_szStatusClassName; if (!RegisterClass (&wc)) { return FALSE; } GetWindowRect(hwndParent, &rc1); g_hwndStatus = CreateWindowEx( WS_EX_TRANSPARENT, g_szStatusClassName, TEXT(""), WS_CHILD, 0, 0, 0, 0, hwndParent, NULL, g_hInstance, NULL ); if (g_hwndStatus == NULL) { UnregisterClass(g_szStatusClassName, g_hInstance); return FALSE; } ShowWindow( g_hwndStatus, SW_HIDE ); return TRUE; } BOOL WINAPI InitProgressBar(HWND hwndParent) { RECT rc1; GetWindowRect(hwndParent, &rc1); g_hwndTimeEstimate = CreateWindowEx( (g_bBiDi?WS_EX_RTLREADING:0), TEXT("STATIC"), NULL, WS_CHILD | (g_bBiDi?SS_RIGHT:SS_LEFT)| SS_NOPREFIX, rc1.left + g_cxEstimate, rc1.top + g_cyEstimate, g_cxEstimateWidth, g_cyEstimateHeight, hwndParent, NULL, g_hInstance, NULL ); if (g_hwndTimeEstimate) { // Set the font for the text in this window SendMessage(g_hwndTimeEstimate, WM_SETFONT, (WPARAM)g_hfont ,0L); SetWindowLongPtr(g_hwndTimeEstimate, GWLP_WNDPROC, (LONG_PTR) StatusSubClassWndProc); ShowWindow(g_hwndTimeEstimate, SW_SHOW); UpdateWindow(g_hwndTimeEstimate); } g_hwndProgressText = CreateWindowEx( (g_bBiDi?WS_EX_RTLREADING:0), TEXT("STATIC"), NULL, WS_CHILD | (g_bBiDi?SS_RIGHT:SS_LEFT)| SS_NOPREFIX, rc1.left + g_cxProgressText, rc1.top + g_cyProgressText, g_cxProgressTextWidth, g_cyProgressTextHeight, hwndParent, NULL, g_hInstance, NULL ); if (g_hwndProgressText) { // Save the original position GetWindowRect(g_hwndProgressText , &g_rcProgressText); SendMessage( g_hwndProgressText, WM_SETFONT, (WPARAM)g_hfont ,0L ); SetWindowLongPtr(g_hwndProgressText, GWLP_WNDPROC, (LONG_PTR) StatusSubClassWndProc); ShowWindow( g_hwndProgressText, SW_SHOW ); UpdateWindow( g_hwndProgressText ); } g_hwndProgressGauge = CreateWindow( PROGRESS_CLASS, NULL, WS_CHILD | PBS_SMOOTH , rc1.left + g_cxGauge, rc1.top + g_cyGauge, g_cxGaugeWidth, g_cyGaugeHeight, hwndParent, NULL, g_hInstance, NULL ); if (g_hwndProgressGauge) { SetWindowLongPtr(g_hwndProgressGauge, GWLP_WNDPROC, (LONG_PTR) ProgressSubClassWndProc); SendMessage( g_hwndProgressGauge, PBM_SETBKCOLOR, 0L, (LPARAM) g_colGaugeBg ); SendMessage( g_hwndProgressGauge, PBM_SETBARCOLOR, 0L, (LPARAM) g_colGauge ); } g_hwndInfoText = CreateWindowEx( (g_bBiDi?WS_EX_RTLREADING:0), TEXT("STATIC"), NULL, WS_CHILD | (g_bBiDi?SS_RIGHT:SS_LEFT)| SS_NOPREFIX, rc1.left + g_cxInfoText, rc1.top + g_cyInfoText, g_cxInfoTextWidth, g_cyInfoTextHeight, hwndParent, NULL, g_hInstance, NULL); if (g_hwndInfoText) { // Set the font for the text in this window SendMessage(g_hwndInfoText, WM_SETFONT, (WPARAM)g_hfont ,0L); SetWindowLongPtr(g_hwndInfoText, GWLP_WNDPROC, (LONG_PTR) StatusSubClassWndProc); ShowWindow(g_hwndInfoText, SW_SHOW); UpdateWindow(g_hwndInfoText); } g_hbmWinLogo = LoadImage( g_hInstance, MAKEINTRESOURCE(g_idbLogo), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR ); if (g_hbmWinLogo) { BITMAP bm; if (GetObject(g_hbmWinLogo, sizeof(BITMAP), &bm)) { g_hwndLogo = CreateWindow(TEXT("STATIC"), NULL, WS_VISIBLE | WS_CHILD | SS_OWNERDRAW, rc1.left + g_cxLogo, rc1.top + g_cyLogo, bm.bmWidth, bm.bmHeight, hwndParent, NULL, g_hInstance, NULL); if (g_hwndLogo) { SetWindowLongPtr(g_hwndLogo, GWLP_WNDPROC, (LONG_PTR) StatusSubClassWndProc); } } } return TRUE; } LRESULT CALLBACK StatusSubClassWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /*++ Routine Description: Subclass the Static Text control used in Billboard and override the WM_ERASEBKGND message, so that the bitmap background can be shown behind the text. Arguments: hwnd - hwnd to a static text window, which must be a child window of the main billboard window msg - (see MSDN) wParam - (see MSDN) lParam - (see MSDN) Return Value: (see MSDN) --*/ { LRESULT lRet; // don't process any message before the CreateWindow of the // main window return and g_hwnd is set. if (g_hwnd != NULL && msg == WM_ERASEBKGND) { lRet = OnEraseBkgnd(hwnd, wParam, lParam); } else { WNDPROC fpStaticWndProc = (WNDPROC) GetClassLongPtr(hwnd, GCLP_WNDPROC); lRet = CallWindowProc(fpStaticWndProc, hwnd, msg, wParam, lParam); } return lRet; } LRESULT CALLBACK ProgressSubClassWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /*++ Routine Description: Subclass the Progress bar control used in Billboard and override the WM_NCPAINT message, so as to draw a flat progress bar. Arguments: hwnd - hwnd to a progress bar window msg - (see MSDN) wParam - (see MSDN) lParam - (see MSDN) Return Value: (see MSDN) --*/ { LRESULT lRet; if (msg == WM_NCPAINT) { RECT rc; if (GetWindowRect(hwnd, &rc)) { HDC hdc = GetWindowDC(hwnd); if (hdc != NULL) { HBRUSH hbrOld; HPEN hpnOld; hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH)); hpnOld = SelectObject(hdc, GetStockObject(BLACK_PEN)); Rectangle(hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top); SelectObject(hdc, hpnOld); SelectObject(hdc, hbrOld); ReleaseDC(hwnd, hdc); } } lRet = 0; } else { WNDPROC fpStaticWndProc = (WNDPROC) GetClassLongPtr(hwnd, GCLP_WNDPROC); if (fpStaticWndProc) { lRet = CallWindowProc(fpStaticWndProc, hwnd, msg, wParam, lParam); } } return lRet; } //--------------------------------------------------------------------------- // // RedCarpetWndProc // //--------------------------------------------------------------------------- LRESULT CALLBACK RedCarpetWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HBRUSH hbr = NULL; switch (msg) { case WM_CREATE: { HDC hdc; hbr = (HBRUSH) GetStockObject( HOLLOW_BRUSH ); // The order of the following function matters, because some // required global variables being initialized before it is // called SetFontCharSet(); SetFontColor(hwnd); GetMyFontsFromFile(); CreateInfoBarFonts(); GetMyImagesFromFile(hwnd); if (BufferBackground(hwnd) == FALSE) { return -1; } SetLayoutParams(); if (InitRealBillBoard(hwnd) == FALSE) { return -1; } if (InitInfoBar(hwnd) == FALSE) { return -1; } if (InitProgressBar(hwnd) == FALSE) { return -1; } if (InitStatus(hwnd) == FALSE) { return -1; } return 0; } case WM_DISPLAYCHANGE: // NOTE: Only top level window can receive this message // i.e. Assertion failure can't be caught if g_hwnd is not // a top-level window BB_ASSERT(FALSE); break; case WM_PAINT: { HDC hdc; PAINTSTRUCT ps; HDC hdcMem; hdc = BeginPaint(hwnd, &ps); if (hdc != NULL) { hdcMem = GetBackgroundBuffer(); BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdcMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); EndPaint(hwnd, &ps); } return(0); } case WM_CTLCOLORSTATIC: { HWND hwndChild; HDC hdcChild; hwndChild = (HWND) lParam; hdcChild = (HDC) wParam; SetTextColor(hdcChild, g_colInfoText); SetBkMode( hdcChild, TRANSPARENT ); if (hwndChild == g_hwndTimeEstimate || hwndChild == g_hwndInfoText) { SelectObject(hdcChild, g_hfontBold); } return (LRESULT)(HBRUSH)hbr; } case WM_DRAWITEM: { LPDRAWITEMSTRUCT pDi = (LPDRAWITEMSTRUCT) lParam; RECT rc; if (GetClientRect(pDi->hwndItem, &rc)) { DrawTransparentBitmap(pDi->hDC, g_hbmWinLogo, rc.left, rc.top, g_colLogoTransparency); } return TRUE; } case WM_DESTROY: if (GetBackgroundBuffer() != NULL) { DestroyBackgroundBuffer(); } if (g_hbmWinLogo) { DeleteObject(g_hbmWinLogo); g_hbmWinLogo = NULL; } hbr = NULL; break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } LRESULT CALLBACK BillBoardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static BOOL fTimerOn = FALSE; static BOOL fAnimate = FALSE; HDC hdc; switch (msg) { case WM_CREATE: { hdc = GetDC(NULL); g_nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); ReleaseDC(NULL, hdc); break; } case WM_PAINT: { PAINTSTRUCT ps; hdc = BeginPaint(hwnd, &ps); if (hdc) { HDC hdcBillboardMem; if (fAnimate) { if (GetBillboardBuffer()) { DestroyBillboardBuffer(); } if (InitAnimate(hwnd, hdc)) { BufferBillboard(hwnd, hdc); } fAnimate = FALSE; } hdcBillboardMem = GetBillboardBuffer(); if (hdcBillboardMem) { BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdcBillboardMem, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); } } EndPaint(hwnd, &ps); return(0); } case WM_START_TIMER: if (!fTimerOn) { if (g_uiLastAnimateIndex == (UINT)-1) g_uiAnimateIndex = 0; else g_uiAnimateIndex = g_uiLastAnimateIndex; if (SetTimer(hwnd, BILLBRD_TEXT_TIMERID, BB_TEXT_DISPLAY, NULL)) { fTimerOn = TRUE; fAnimate = TRUE; ShowWindow(hwnd, SW_SHOW); } } return fTimerOn; case WM_STOP_TIMER: if (fTimerOn) { fTimerOn = FALSE; g_uiLastAnimateIndex = g_uiAnimateIndex; g_uiAnimateIndex = (UINT)-1; KillTimer(hwnd, BILLBRD_TEXT_TIMERID); ShowWindow(hwnd, SW_HIDE); } return fTimerOn == FALSE; case WM_TIMER: { AnimateNext(); fAnimate = TRUE; InvalidateRect(hwnd, NULL, FALSE); UpdateWindow(hwnd); } break; case WM_DESTROY: TerminateAnimate(); if (fTimerOn) { fTimerOn = FALSE; g_uiLastAnimateIndex = g_uiAnimateIndex; g_uiAnimateIndex = (UINT) -1; KillTimer(hwnd, BILLBRD_TEXT_TIMERID); } if (GetBillboardBuffer() != NULL) { DestroyBillboardBuffer(); } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } LRESULT CALLBACK AnimationWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { // // Hardcoded animation properties // static const DWORD BitmapIds[][4] = { { IDB_INTENSITY1_C16BIT, IDB_INTENSITY2_C16BIT, IDB_INTENSITY3_C16BIT, IDB_INTENSITY4_C16BIT }, { IDB_INTENSITY1_C4BIT, IDB_INTENSITY2_C4BIT, IDB_INTENSITY3_C4BIT, IDB_INTENSITY4_C4BIT } }; static const DWORD SrvBitmapIds[][4] = { { IDB_SRV_INTENSITY1_C16BIT, IDB_SRV_INTENSITY2_C16BIT, IDB_SRV_INTENSITY3_C16BIT, IDB_SRV_INTENSITY4_C16BIT }, { IDB_SRV_INTENSITY1_C4BIT, IDB_SRV_INTENSITY2_C4BIT, IDB_SRV_INTENSITY3_C4BIT, IDB_SRV_INTENSITY4_C4BIT, } }; static const int OriginalBitmapSize = 9; static BOOL fTimerOn = FALSE; static HBITMAP Bitmaps[] = {NULL, NULL, NULL, NULL}; static const int NumBitmaps = sizeof(Bitmaps) / sizeof(HBITMAP); static int BoxToFade = 0; static int BoxBitmapIndex[] = {0, 0, 0, 0, 0}; static const int NumBoxes = sizeof(BoxBitmapIndex) / sizeof(DWORD); static int BitmapSize = 0; switch (msg) { case WM_CREATE: { int Set; int i; int Ret = 0; HDC hdc; hdc = GetDC(hwnd); if (hdc != NULL) { Set = (GetDeviceCaps(hdc, BITSPIXEL) > 8) ? 0 : 1; ReleaseDC(hwnd, hdc); } else { Set = 1; } // // The bitmaps are designed for 640 x 480. We want to scale them by // 80% of the ratio between the current screen with and 640 // BitmapSize = OriginalBitmapSize * GetSystemMetrics(SM_CXSCREEN) * 8 / 6400; for (i = 0; i < NumBitmaps; i++) { if ((dwBBTextType == 0) || (dwBBTextType == 4)) { Bitmaps[i] = LoadImage( g_hInstance, MAKEINTRESOURCE(BitmapIds[Set][i]), IMAGE_BITMAP, BitmapSize, BitmapSize, LR_DEFAULTCOLOR); } else { Bitmaps[i] = LoadImage( g_hInstance, MAKEINTRESOURCE(SrvBitmapIds[Set][i]), IMAGE_BITMAP, BitmapSize, BitmapSize, LR_DEFAULTCOLOR); } if (!Bitmaps[i]) { Ret = -1; break; } } if (Ret == 0) { int Width; int Height; BoxBitmapIndex[0] = NumBitmaps - 1; for (i = 1; i < NumBoxes; i++) { BoxBitmapIndex[i] = 0; } BoxToFade = 0; Width = BitmapSize * (NumBoxes * 2 - 1); Height = BitmapSize; MoveWindow( hwnd, GetSystemMetrics(SM_CXSCREEN) - g_cxSteps - Width, g_cyBillBrd + g_cyBillBrdHeight + (g_cyBannerHeight - Height) / 2, Width, Height, FALSE ); } else { int j; for (j = 0; j < i; j++) { DeleteObject(Bitmaps[j]); } } return Ret; } case WM_ERASEBKGND: { return OnEraseBkgnd(hwnd, wParam, lParam); } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = NULL; int i = 0; hdc = BeginPaint(hwnd, &ps); if (hdc != NULL) { for (i = 0; i < NumBoxes; i++) { DrawBitmap( hdc, Bitmaps[BoxBitmapIndex[i]], i * (BitmapSize * 2), 0 ); } } EndPaint(hwnd, &ps); return(0); } case WM_START_TIMER: if (!fTimerOn) { if (SetTimer(hwnd, WHISTLER_PROGRESS_TIMERID, BB_WHISTLER_MOVE, NULL)) { fTimerOn = TRUE; ShowWindow(hwnd, SW_SHOW); } } return fTimerOn; case WM_STOP_TIMER: if (fTimerOn) { fTimerOn = FALSE; KillTimer(hwnd, WHISTLER_PROGRESS_TIMERID); ShowWindow(hwnd, SW_HIDE); } return fTimerOn == FALSE; case WM_TIMER: { if (BoxBitmapIndex[BoxToFade] == 0) { BoxToFade = (BoxToFade + 1) % NumBoxes; } else { DWORD BoxToGrow = (BoxToFade + 1) % NumBoxes; BoxBitmapIndex[BoxToFade]--; BoxBitmapIndex[BoxToGrow]++; } InvalidateRect(hwnd, NULL, FALSE); UpdateWindow(hwnd); } break; case WM_DESTROY: { int i; if (fTimerOn) { fTimerOn = FALSE; KillTimer(hwnd, WHISTLER_PROGRESS_TIMERID); } for (i = 0; i < NumBitmaps; i++) { if (Bitmaps[i]) { DeleteObject(Bitmaps[i]); } } } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } //--------------------- // DLL export functions //--------------------- BOOL WINAPI TermBillBoard() { BOOL b = TRUE; if (g_hwnd) { if (!DestroyWindow(g_hwnd)) { return FALSE; } g_hwnd = NULL; b = UnregisterClass(g_szStepsClassName, g_hInstance); b = b && UnregisterClass(g_szBillBoardClassName, g_hInstance); b = b && UnregisterClass(g_cszClassName, g_hInstance); b = b && UnregisterClass(g_szStatusClassName, g_hInstance); } return b; } BOOL WINAPI InitBillBoard(HWND hwndParent, LPCTSTR lpszPath, DWORD dwInstallType) { WNDCLASS wc; HWND hwnd; TCHAR Buffer[128]; if (dwInstallType < (sizeof(bb_text) / sizeof(bb_text[0]))) { dwBBTextType = dwInstallType; } if (LoadString(g_hInstance, IDD_PANELCOUNT, (LPTSTR)Buffer, sizeof(Buffer)/sizeof(TCHAR))) g_nPanelCount = MyAtoI((const TCHAR*)Buffer); else g_nPanelCount = 0; g_nPanelCount++; if (LoadString(g_hInstance, IDD_ANIMATION, (LPTSTR)Buffer, sizeof(Buffer)/sizeof(TCHAR))) g_nAnimID = MyAtoI((const TCHAR*)Buffer); else g_nAnimID = 0; if ((g_szPath[0] == '\0') && (lpszPath == NULL)) //can't go on without path return FALSE; if (hwndParent == NULL) hwnd = GetDesktopWindow(); else hwnd = hwndParent; if(g_szPath[0] == '\0') { lstrcpy((LPTSTR)g_szPath, (LPCTSTR)lpszPath); AddPath(g_szPath, TEXT("BILLBRD")); lstrcpy(g_szFileName, g_szPath); //append .ini filename to path AddPath(g_szFileName, TEXT("winntbb.ini")); } wc.style = (UINT)CS_BYTEALIGNWINDOW; wc.lpfnWndProc = RedCarpetWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hInstance; wc.hIcon = LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_SETUP)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = g_cszClassName; if (!RegisterClass (&wc)) return FALSE; LoadString(g_hInstance,IDS_WINNT_SETUP,(LPTSTR)Buffer,sizeof(Buffer)/sizeof(TCHAR)); // If we have a parent, be a child window. // If not be a main window. g_hwnd = CreateWindow( g_cszClassName, (LPTSTR)Buffer, (hwndParent ? WS_CHILD : WS_POPUP) | WS_CLIPCHILDREN, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), hwnd, NULL, g_hInstance, NULL ); if (g_hwnd == NULL) { UnregisterClass(g_cszClassName, g_hInstance); return FALSE; } ShowWindow( g_hwnd, SW_SHOW ); UpdateWindow( g_hwnd ); g_hwndParent = hwnd; return TRUE; } HWND WINAPI GetBBMainHwnd() { return g_hwnd; } HWND WINAPI GetBBHwnd() { return g_hwndBB; } BOOL WINAPI ShowPanel(int iPanel) { if (g_iCurPanel == iPanel) return FALSE; if ((iPanel >= 0) && (iPanel < g_nPanelCount)) { if (g_hwndBB == NULL) return(FALSE); g_iCurPanel = iPanel; } else { if (g_hwnd) { DestroyWindow(g_hwnd); g_hwnd = NULL; g_iCurPanel = -1; } } return(TRUE); } int WINAPI GetPanelCount() { return(g_nPanelCount); } void WINAPI BB_Refresh(void) { if(g_hwnd) { RedrawWindow( g_hwnd, NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW | RDW_INVALIDATE); } } BOOL WINAPI SetProgress(WORD wProgress) { if (wProgress == 0xffff) { // Kill the last panel... return ShowPanel(wProgress); } else if (wProgress & 0x8000) { // Display a specific panel return ShowPanel(wProgress & 0x7fff); } else { // Normal case of a percentage... return ShowPanel((g_nPanelCount * wProgress)/100); } } BOOL WINAPI StartBillBoard() { BOOL retval = FALSE; if(g_hwnd && g_hwndBB) { retval = (BOOL) SendMessage(g_hwndBB, WM_START_TIMER, 0, 0L); if (g_hwndStatus) { SendMessage(g_hwndStatus, WM_START_TIMER, 0, 0L); } } return retval; } BOOL WINAPI StopBillBoard() { BOOL retval = FALSE; if(g_hwnd && g_hwndBB) { retval = (BOOL) SendMessage(g_hwndBB, WM_STOP_TIMER, 0, 0L); if (g_hwndStatus) { SendMessage(g_hwndStatus, WM_STOP_TIMER, 0, 0L); } } return retval; } BOOL WINAPI ShowProgressGaugeWindow(UINT uiShow) { BOOL bRet; if (uiShow == SW_HIDE) { bRet = ShowWindow(g_hwndProgressGauge, uiShow); // If we hide the progress bar, reset the progress position // OC manager does a PBM_SETRANGE, but does not call PBM_SETPOS SendMessage(g_hwndProgressGauge, PBM_SETPOS, 0, 0); } else { bRet = ShowWindow(g_hwndProgressGauge, uiShow); } return bRet; } BOOL AdjustProgressTextWindow(HWND hwnd, LPCTSTR szText) { BOOL rc; HDC hdc; RECT rect; RECT rect2; LONG height1,height2,delta; HFONT hFontOld = NULL; // Use the original position to calc the new position rect.top = g_rcProgressText.top; rect.bottom = g_rcProgressText.bottom; rect.left = g_rcProgressText.left; rect.right = g_rcProgressText.right; rect2.top = g_rcProgressText.top; rect2.bottom = g_rcProgressText.bottom; rect2.left = g_rcProgressText.left; rect2.right = g_rcProgressText.right; hdc = GetDC(hwnd); if (hdc == NULL) { rc = FALSE; } else { // Select the font into the DC so that DrawText can calc the size correct. hFontOld = SelectObject(hdc, g_hfont); DrawText(hdc, szText, -1, &rect2, DT_CALCRECT|DT_EXTERNALLEADING|DT_WORDBREAK); if(hFontOld) { SelectObject(hdc, hFontOld); } ReleaseDC(hwnd, hdc); // Calc the new height for the string height2 = rect2.bottom - rect2.top; // get the old height height1 = rect.bottom - rect.top; // See how far we have to change the top of the rect. delta = (height1 - height2); rect.top += delta; // If we would get above the original position, don't if (rect.top < g_rcProgressText.top) { rect.top = g_rcProgressText.top; } // Since the privous window position could be different from the original, always move // the window. MoveWindow(hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,TRUE); rc = TRUE; } return rc; } BOOL WINAPI SetProgressText(LPCTSTR szText) { TCHAR Empty[] = TEXT(""); if (g_hwndProgressText) { ShowWindow(g_hwndProgressText, SW_HIDE); if (szText) { AdjustProgressTextWindow(g_hwndProgressText, szText); SendMessage(g_hwndProgressText, WM_SETTEXT, 0, (LPARAM) szText); } else { SendMessage(g_hwndProgressText, WM_SETTEXT, 0, (LPARAM) Empty); } ShowWindow(g_hwndProgressText, SW_SHOW); } return TRUE; } LRESULT WINAPI ProgressGaugeMsg(UINT msg, WPARAM wparam, LPARAM lparam) { LRESULT lresult = 0; if (g_hwndProgressGauge) { lresult = (LRESULT) SendMessage(g_hwndProgressGauge, msg, wparam, lparam); } return lresult; } BOOL WINAPI SetTimeEstimate(LPCTSTR szText) { TCHAR Empty[] = TEXT(""); if (g_hwndTimeEstimate ) { ShowWindow(g_hwndTimeEstimate, SW_HIDE); if (szText) { SendMessage(g_hwndTimeEstimate , WM_SETTEXT, 0, (LPARAM) szText); } else { SendMessage(g_hwndTimeEstimate , WM_SETTEXT, 0, (LPARAM) Empty); } ShowWindow(g_hwndTimeEstimate, SW_SHOW); } return TRUE; } BOOL WINAPI SetStep(int iPanel) { BOOL rc = FALSE; if (g_hwndSteps) { rc = (BOOL) SendMessage(g_hwndSteps, WM_SETSTEP, 0, (LPARAM) iPanel); } return rc; } BOOL WINAPI SetInfoText(LPCTSTR szText) { TCHAR Empty[] = TEXT(""); if (g_hwndInfoText) { ShowWindow(g_hwndInfoText, SW_HIDE); if (szText) { SendMessage(g_hwndInfoText, WM_SETTEXT, 0, (LPARAM) szText); } else { SendMessage(g_hwndInfoText, WM_SETTEXT, 0, (LPARAM) Empty); } ShowWindow(g_hwndInfoText, SW_SHOW); } return TRUE; }