/* Copyright (c) Microsoft Corporation. Licensed under the MIT License. */ /******************************************************************* * * CREDITS.CPP * * Copyright (C) Microsoft Corporation 1993. * All Rights reserved. * ******************************************************************* * * Description: ***** main stack procedures. * * Current Owner: ***** * * *****: This module needs a code review in a bad way!! * ******************************************************************* * * Revision History: * 09/01/94 ***** Created * 10/09/94 ***** Modified PID box code so the text is in the * disc resource file (eg Nature.rc) * 10/14/94 ***** Changed gadget cursor to fly with wings in * 04/14/95 ***** MediaView 1.4 port * 04/19/95 ***** MediaView & 16bit clean up * 04/25/95 ***** Win32 port * 06/20/95 ***** Created PID dialog for System Info button * 07/01/95 ***** Fixed resource modification and memory allocation bugs in PID DlgProc * 07/03/95 ***** locked PID dialog's colors * 07/06/95 ***** modified version-checking to use import libs * 07/07/95 ***** Fixed PID dialog, accepts default buttons and hotkeys * 07/10/95 ***** Modified PID for version 2.0 of PID * 07/11/95 ***** Fixed minor bug preventing PID 2.0 text from being visible * 07/11/95 ***** Fixed centering of PID after res-switch and task-switch * 07/12/95 ***** PID box uses Arial font * 07/17/95 ***** Credits screen rejects screen saver * ******************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "credits.h" #include #ifdef WIN32 #include #else #include #endif #include #define OK_X 566 #define OK_Y 409 // function protos BOOL fLoadCreditResources(void); void vTermCreditResources(void); BOOL CALLBACK _loadds fPIDDlg(HWND, UINT, WPARAM, LPARAM); // Globals BOOL gfCreditsMagSet = FALSE; extern SENUTILSTATE SenUtilState; LPBITMAPINFO lpbmGadget = NULL; LPBITMAPINFO lpbmOK = NULL; LPBITMAPINFO lpbmSeeAlso = NULL; LPBITMAPINFO lpbmMore = NULL; LPBITMAPINFO lpbmLess = NULL; HTITLE ghCreditTitle; FINDINFO CreditInfo; extern HDC gWinGDC; extern INFO_HEADER gWinGInfoHeader; extern void far * gpWinGBits; #define GWL_LPCREDITMV 0 #define CMD_CREDITPREV 101 #define CMD_CREDITMORE 102 #define CHILD_ID 103 #define CREDITS_DX (POPUP_DX - 2) /******************************************************************/ /* @doc EXTERNAL @func RC | rcShowCredits | Entry point into displaying the credits. @parm HWND | hWndParent | Parent window handle. @rdesc A return code. */ RC WINAPI _loadds rcShowCredits(HWND hWndParent) { char rgchClassName[MAX_CLASS_NAME]; RECT rect; // If missions up... disable this! if ( hGetMissionsWnd(NULL) ) return RC_OK; // WIN32: Must center based on matt window for Win95 resolution-changing/task-switching bug GetWindowRect(lpGetSenState()->hMattWnd, &rect); rect.left += (rect.right -rect.left - STACK_WIDTH) / 2; rect.top += (rect.bottom -rect.top - STACK_HEIGHT) / 2; // Shut down SPAM prior to creating the WINDOW! (lpGetSenState()->lpTitleAction)(SENSPAM_SPAM_ENABLE, FALSE, 0); if ( gWinGDC == NULL ) { DPF("rcShowCredits Initing the WinG bitmap\n"); if ( !fInitWinG(SenUtilState.hInst, NULL, 640, 480) ) return RC_NOMEM; } if ( !fLoadCreditResources() ) goto error; if ( !LoadString(SenUtilState.hInst, STBL_CLS_CREDITS, rgchClassName, MAX_CLASS_NAME) ) goto error; if ( (CreateWindow(rgchClassName, rgchClassName, WS_POPUP | WS_VISIBLE, rect.left, rect.top, STACK_WIDTH, STACK_HEIGHT, hWndParent, (HMENU)NULL, SenUtilState.hInst, NULL)) == NULL ) { DPF("rcShowCredits: Error, could not create Credits Window\n"); goto error; } // Set our StackWinG dirty flag! fStackWinGDirty = TRUE; // Clear out our WING buffer! vClearWinGBuffer(); return RC_OK; error: // Free any bitmaps that may have been created! vTermCreditResources(); // Free our WinG thing DPF("rcShowCredits terminating WinG bitmap\n"); vTermWinG(NULL); // Activate SPAM upon this error! (lpGetSenState()->lpTitleAction)(SENSPAM_SPAM_ENABLE, TRUE, 0); return RC_NOMEM; } BOOL fLoadCreditResources() { // Load our bitmaps! if ( (lpbmGadget = lpLoadDibResource(SenUtilState.hInst, MAKEINTRESOURCE(BM_GADGET))) == NULL ) return FALSE; if ( (lpbmOK = lpLoadDibResource(SenUtilState.hInst, MAKEINTRESOURCE(BM_OK))) == NULL ) return FALSE; if ( (lpbmSeeAlso = lpLoadDibResource(SenUtilState.hInst, MAKEINTRESOURCE(BM_SEEALSO))) == NULL ) return FALSE; if ( (lpbmMore = lpLoadDibResource(SenUtilState.hInst, MAKEINTRESOURCE(BM_MORE))) == NULL ) return FALSE; if ( (lpbmLess = lpLoadDibResource(SenUtilState.hInst, MAKEINTRESOURCE(BM_LESS))) == NULL ) return FALSE; return TRUE; } void vTermCreditResources() { if ( lpbmGadget ) { vUnloadDibResource(lpbmGadget); lpbmGadget = NULL; } if ( lpbmOK ) { vUnloadDibResource(lpbmOK); lpbmOK = NULL; } if ( lpbmSeeAlso ) { vUnloadDibResource(lpbmSeeAlso); lpbmSeeAlso = NULL; } if ( lpbmMore ) { vUnloadDibResource(lpbmMore); lpbmMore = NULL; } if ( lpbmLess ) { vUnloadDibResource(lpbmLess); lpbmLess = NULL; } } /******************************************************************/ /* @doc EXTERNAL @func LRESULT | lCreditsWndProc | Main Window procedure for credits. @param HWND | hWnd | Window handle. @param UINT | message | Window message. @param WPARAM | wParam | Message dependant parameter. @param LPARAM | lParam | Message dependant parameter. @rdesc Message dependant. */ extern "C" LRESULT CALLBACK lCreditsWndProc(HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam) { switch (wMessage) { //HANDLE_MSG(hWnd, WM_KILLFOCUS, CreditsWnd_OnKillFocus); HANDLE_MSG(hWnd, WM_CREATE, CreditsWnd_OnCreate); HANDLE_MSG(hWnd, WM_DESTROY, CreditsWnd_OnDestroy); HANDLE_MSG(hWnd, WM_PAINT, CreditsWnd_OnPaint); HANDLE_MSG(hWnd, WM_COMMAND, CreditsWnd_OnCommand); HANDLE_MSG(hWnd, WM_PALETTECHANGED, OnPaletteChanged); HANDLE_MSG(hWnd, WM_QUERYNEWPALETTE, OnQueryNewPalette); HANDLE_MSG(hWnd, WM_KEYDOWN, CreditsWnd_OnKey); case WM_SYSCOMMAND: if (wParam == SC_SCREENSAVE) { DPF("Balloon ScreenSaver: REJECTED!!!\n"); return (TRUE); // reject the screen saver } break; } return DefWindowProc(hWnd, wMessage, wParam, lParam); } /******************************************************************/ /* This function is to deal with ALT+F6 */ /* void CreditsWnd_OnKillFocus(HWND hwnd, HWND hwndNewFocus) { if (hwndNewFocus == GetParent(lpGetSenState()->hMattWnd)) FORWARD_WM_COMMAND(hwnd, CMD_CLOSE, NULL, 0, PostMessage); } */ /******************************************************************/ /* @doc EXTERNAL @func BOOL | CreditsWnd_OnCreate WM_CREATE message cracker for main stack. @param HWND | hWnd | Window handle. @param LPCREATESTRUCT | lpCreateStruct | Pointer to window creation structure. @rdesc TRUE upon succes, FALSE otherwise. */ BOOL CreditsWnd_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct) { char rgchMVClass[MAX_CLASS_NAME]; MMBUTTONCS Button; // Register palette handler vRegisterPalette(hWnd, TRUE); if ( !LoadString(lpCreateStruct->hInstance, STBL_CLS_MVCHILD, rgchMVClass, MAX_CLASS_NAME) ) return FALSE; // Create child windows Button.NumTiles = 2; Button.NextButtonID = 0; Button.lpBmp = lpbmOK; Button.wForSnd = (WORD)(SD_OFFBUTT); Button.iTop = 0; Button.wBltMode = BLT_GADGET; if ( (CreateWindow( lpszMMButton, NULL, WS_CHILD | WS_VISIBLE, OK_X, OK_Y, Button.lpBmp->bmiHeader.biWidth/2, Button.lpBmp->bmiHeader.biHeight, hWnd, (HMENU)(CMD_CLOSE), lpCreateStruct->hInstance, (LPVOID)&Button)) == NULL ) { DPF("Couldn't create OFF button!\n"); return FALSE; } Button.lpBmp = lpbmSeeAlso; Button.wForSnd = SD_SEEALSO; if ( (CreateWindow( lpszMMButton, NULL, WS_CHILD | WS_VISIBLE, SEEALSO_BUTT_X, SEEALSO_BUTT_Y, Button.lpBmp->bmiHeader.biWidth/2, Button.lpBmp->bmiHeader.biHeight, hWnd, (HMENU)(CMD_SEEALSO), lpCreateStruct->hInstance, (LPVOID)&Button)) == NULL ) { DPF("Couldn't create info button\n"); return FALSE; } Button.wBltMode = BLT_GADGET; Button.wForSnd = SD_BUTT1 + BUTT_LESS; Button.lpBmp = lpbmLess; Button.NumTiles = 14; Button.iTop = 0; if ((CreateWindow(lpszMMButton, NULL, WS_CHILD | MMBS_Check, //starts off hidden, and is a MMBS_Check to prevent reversing MED_BUTT_X, MED_BUTT_Y, Button.lpBmp->bmiHeader.biWidth / Button.NumTiles, Button.lpBmp->bmiHeader.biHeight, hWnd, (HMENU)(CMD_CREDITPREV), lpCreateStruct->hInstance, (LPVOID)&Button)) == NULL ) { DPF("Couldn't create less button\n"); return FALSE; } Button.wBltMode = BLT_GADGET; Button.wForSnd = SD_BUTT1 + BUTT_MORE; Button.lpBmp = lpbmMore; Button.NumTiles = 13; if ((CreateWindow(lpszMMButton, NULL, WS_CHILD | WS_VISIBLE | MMBS_Check, MED_BUTT_X, MED_BUTT_Y, // starts off as only button Button.lpBmp->bmiHeader.biWidth / Button.NumTiles, Button.lpBmp->bmiHeader.biHeight, hWnd, (HMENU)(CMD_CREDITMORE), lpCreateStruct->hInstance, (LPVOID)&Button)) == NULL ) { DPF("Couldn't create more button\n"); return FALSE; } if ( (CreateWindow( rgchMVClass, rgchMVClass, WS_CHILD | WS_VISIBLE | WS_VSCROLL, POPUP_X, POPUP_Y, CREDITS_DX, POPUP_DY, hWnd, (HMENU)CHILD_ID, lpCreateStruct->hInstance, NULL)) == NULL ) { DPF("Couldn't create MVChild window!\n"); return FALSE; } DPF3("\n"); return TRUE; } /******************************************************************/ /* @doc EXTERNAL @func void | CreditsWnd_OnDestroy WM_DESTROY message cracker for Credits. @param HWND | hWnd | Window handle. @rdesc Nothing. */ void CreditsWnd_OnDestroy(HWND hWnd) { // Tell the palette manager we are done vRegisterPalette(hWnd, FALSE); gfCreditsMagSet = FALSE; // Free resources vTermCreditResources(); // Free WinG thing DPF("Credits terminating WinG bitmap\n"); vTermWinG(NULL); } /****************************************************************************** @func void | CreditsWnd_OnPaint | WM_PAINT message handler. ******************************************************************************/ void CreditsWnd_OnPaint(HWND hWnd) { DPF4("CreditsWnd_OnGadgetPaint: Entering...\n"); PAINTSTRUCT ps; BeginPaint(hWnd, &ps); HPALETTE hPal = lpGetSenState()->hPal; SETPALETTE(ps.hdc, hPal); #ifdef NEWTRANSBLT TransparentDIBits((BITMAPINFO far *)&gWinGInfoHeader, gpWinGBits, 0, 0, DibPtr((LPBITMAPINFOHEADER)lpbmGadget), DibInfo((LPBITMAPINFOHEADER)lpbmGadget), 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, 0xFF); #else TransparentDIBits((BITMAPINFO far *)&gWinGInfoHeader, gpWinGBits, 0, 0, DibPtr((LPBITMAPINFOHEADER)lpbmGadget), DibInfo((LPBITMAPINFOHEADER)lpbmGadget), 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, TRUE, 0xFF); #endif WinGBitBlt(ps.hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, gWinGDC, 0, 0); EndPaint(hWnd, &ps); DPF4("CreditsWnd_OnGadgetPaint: Exiting...\n"); } /******************************************************************/ /* @doc EXTERNAL @func void | CreditsWnd_OnCommand WM_COMMAND message cracker for credits. @parm HWND | hWnd | Window handle. @parm int | iCtlID | Control ID value. @parm HWND | hWndCtl | Window handle to control. @parm UINT | wNotify | Notification message. @rdesc Nothing. */ void CreditsWnd_OnCommand(HWND hWnd, int iCtlID, HWND, UINT) { DPF("Command id is: %d\n", iCtlID); switch(iCtlID) { case CMD_CLOSE: PostMessage(hWnd, WM_CLOSE, NULL, NULL); break; case CMD_SEEALSO: vShowPid(hWnd); break; case CMD_CREDITPREV: RECT rcWindow; MMB_SetState(GetDlgItem(hWnd, CMD_CREDITPREV), MMB_FirstState); // reset the window if (CreditInfo.lFindPos == CreditInfo.lWWLength - 1) { ShowWindow(GetDlgItem(hWnd, CMD_CREDITMORE), TRUE); } CreditInfo.lFindPos--; vGetCreditTopic(GetDlgItem(hWnd, CHILD_ID)); if (CreditInfo.lFindPos == 0) { HWND hWndTemp = GetDlgItem(hWnd, CMD_CREDITMORE); GetClientRect(hWndTemp, &rcWindow); ShowWindow(GetDlgItem(hWnd, CMD_CREDITPREV), FALSE); MoveWindow(hWndTemp, MED_BUTT_X, MED_BUTT_Y, rcWindow.right, rcWindow.bottom, TRUE); } break; case CMD_CREDITMORE: MMB_SetState(GetDlgItem(hWnd, CMD_CREDITMORE), MMB_FirstState); // reset the window if (CreditInfo.lFindPos == 0) { RECT rcWindow; HWND hWndTemp = GetDlgItem(hWnd, CMD_CREDITMORE); GetClientRect(hWndTemp, &rcWindow); ShowWindow(GetDlgItem(hWnd, CMD_CREDITPREV), TRUE); MoveWindow(hWndTemp, MED_BUTT_X, MED_BUTT_Y + MED_BUTT_DY, rcWindow.right, rcWindow.bottom, TRUE); } CreditInfo.lFindPos++; vGetCreditTopic(GetDlgItem(hWnd, CHILD_ID)); if (CreditInfo.lFindPos == CreditInfo.lWWLength - 1) { ShowWindow(GetDlgItem(hWnd, CMD_CREDITMORE), FALSE); } break; } } /************************************************************************ MVChildWindow functions ************************************************************************/ /******************************************************************/ /* @doc EXTERNAL @func LRESULT | lCreditsWndProc | Main Window procedure for credits. @param HWND | hWnd | Window handle. @param UINT | message | Window message. @param WPARAM | wParam | Message dependant parameter. @param LPARAM | lParam | Message dependant parameter. @rdesc Message dependant. */ extern "C" LRESULT CALLBACK lMVChildWndProc(HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam) { switch (wMessage) { HANDLE_MSG(hWnd, WM_CREATE, MVChild_OnCreate); HANDLE_MSG(hWnd, WM_DESTROY, MVChild_OnDestroy); HANDLE_MSG(hWnd, WM_PAINT, MVChild_OnPaint); HANDLE_MSG(hWnd, WM_VSCROLL, MVChild_OnVScroll); HANDLE_MSG(hWnd, WM_PALETTECHANGED, OnPaletteChanged); HANDLE_MSG(hWnd, WM_QUERYNEWPALETTE, OnQueryNewPalette); } return DefWindowProc(hWnd, wMessage, wParam, lParam); } /******************************************************************/ /* @doc EXTERNAL @func BOOL | MVChild_OnCreate WM_CREATE message cracker for main stack. @param HWND | hWnd | Window handle. @param LPCREATESTRUCT | lpCreateStruct | Pointer to window creation structure. @rdesc TRUE upon succes, FALSE otherwise. */ BOOL MVChild_OnCreate(HWND hWnd, CREATESTRUCT FAR*) { ERR err; char rgchMVFile[_MAX_PATH]; LPSTR lpszTemp; LPMV lpMV; HANDLE hFntTable; // copy our book path lstrcpy((LPSTR)rgchMVFile, lpGetSenState()->lpszMMIOPath); // Nuke the '+' lpszTemp = rgchMVFile; while ( *lpszTemp && *lpszTemp != '+' ) ++lpszTemp; *lpszTemp = '\0'; if ( (ghCreditTitle = hMVTitleOpen((LPCSTR)rgchMVFile)) == NULL ) { DPF("Credits: Couldn't open title '%s'.\n", rgchMVFile); return FALSE; } else { if ( (lpMV = lpMVNew(ghCreditTitle, (LPERR)&err)) == NULL ) DPF("Credits: Couldn't create MV.\n"); else { MVSetTextColor(lpMV, RGB_BLACK); MVSetBkColor(lpMV, RGB_WHITE); // WIN32: This was casting (HANDLE)(WORD), which would be bad for Win32 hFntTable = (HANDLE)lMVTitleGetInfo(ghCreditTitle, TTLINF_FONTTABLE, 0L, 0L); if(hFntTable) { hMVSetFontTable(lpMV, hFntTable); goto MV_OK; } MVDelete(lpMV); } MVTitleClose(ghCreditTitle); return FALSE; } MV_OK: SetWindowLong(hWnd, GWL_LPCREDITMV, (LONG)lpMV); if ( !fMVSetWindow(lpMV, hWnd, (LPERR)&err) ) return FALSE; // comment this line if bug 3404 gets reopened: // MVHidePartialLines(lpMV, TRUE); vShowInitialTopic(hWnd); DPF3("MVChild Window Created..."); return TRUE; } /******************************************************************/ /* @doc INTERNAL @func void | vShowInitialTopic Opens word wheel and shows topic 0 @param HWND | hWnd | Window handle. @rdesc Nothing. */ void vShowInitialTopic(HWND hWnd) { char rgchText[_MAX_PATH]; LPSTR lpszTemp; lstrcpy((LPSTR)rgchText, lpGetSenState()->lpszMMIOPath); lpszTemp = rgchText; while (*lpszTemp && *lpszTemp != '+') { ++lpszTemp; } *lpszTemp = '\0'; CreditInfo.hWheel = hMVWordWheelOpenTitle(ghCreditTitle, "Credits"); if (CreditInfo.hWheel != NULL) { CreditInfo.lWWLength = lMVWordWheelLength(CreditInfo.hWheel); CreditInfo.lFindPos = 0l; } vGetCreditTopic(hWnd); } /******************************************************************/ /* @doc INTERNAL @func void | vGetCreditTopic | Gets and displays the credit topic referenced by CreditInfo.lFindPos @rdesc Nothing. */ void vGetCreditTopic(HWND hWnd) { char rgchText[128]; DWORD dwContextID; if (!nMVWordWheelLookup(CreditInfo.hWheel, CreditInfo.lFindPos, (LPBYTE)rgchText, 128)) { dwContextID = dwHexToDW(rgchText); DPF("Fetched %s (0x%8lx) from word wheel\n", rgchText, dwContextID); vGotoCredits(hWnd, dwContextID); } else { DPF("Wordwheellookup failed in vGetCreditTopic\n"); } } /******************************************************************/ /* @doc EXTERNAL @func void | CreditsWnd_OnDestroy WM_DESTROY message cracker for Credits. @param HWND | hWnd | Window handle. @rdesc Nothing. */ void MVChild_OnDestroy(HWND hWnd) { DPF4("MVChild OnDestroy\n"); LPMV lpMV = (LPMV)GetWindowLong(hWnd, GWL_LPCREDITMV); DPF("lpMV: %lx\n", (DWORD)lpMV); if(lpMV ) { MVDelete(lpMV); } if (CreditInfo.hWheel != NULL) { MVWordWheelClose(CreditInfo.hWheel); CreditInfo.hWheel = NULL; } } /****************************************************************************** @func void | MVChild_OnPaint | WM_PAINT message handler. ******************************************************************************/ void MVChild_OnPaint(HWND hWnd) { PAINTSTRUCT ps; LPMV lpMV; ERR err; lpMV = (LPMV)GetWindowLong(hWnd, GWL_LPCREDITMV); DPF4("MVChild OnPaint\n"); BeginPaint(hWnd, &ps); if (lpMV) { RECT rectClient; GetClientRect(hWnd, &rectClient); fMVApplyToDC(lpMV, ps.hdc, (LPRECT)&rectClient, (LPERR)&err); } EndPaint(hWnd, &ps); } void MVChild_OnVScroll(HWND hWnd, HWND, UINT code, int pos) { int y; ERR err; POINT pt; // RECT rc; int yTop = 0, yBottom = 0; LPMV lpMV = (LPMV)GetWindowLong(hWnd, GWL_LPCREDITMV); if ( !lpMV ) return; switch (code) { case SB_TOP: case SB_BOTTOM: case SB_LINEUP: case SB_LINEDOWN: case SB_PAGEUP: case SB_PAGEDOWN: y = yMVScrollY(lpMV, &pt, &yTop, &yBottom, code, 0, &err); SetScrollPos (hWnd, SB_VERT, y, TRUE); ScrollWindow(hWnd, pt.x, pt.y, 0, 0); // this doesn't need to be done, and causes flash if it is /* if( (code == SB_LINEUP) || (code == SB_PAGEUP) ) { GetClientRect(hWnd, &rc); rc.top = rc.bottom - yBottom; ScrollWindow(hWnd, 0, yBottom, &rc, NULL); } else if( (code == SB_LINEDOWN) || (code == SB_PAGEDOWN) ) { GetClientRect(hWnd, &rc); rc.bottom = rc.top + yTop; ScrollWindow(hWnd, 0, -yTop, &rc, NULL); } */ break; case SB_THUMBPOSITION: /* * pt comes back empty in this case, but the MediaView has * done the proper layout. Redraw the window */ y = yMVScrollY(lpMV, &pt, &yTop, &yBottom, code, pos, (LPERR)&err); SetScrollPos(hWnd, SB_VERT, y, TRUE); RedrawWindow(hWnd, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); UpdateWindow(hWnd); break; case SB_THUMBTRACK: /* track thumb, but don't update the display until SB_THUMBPOSITION */ SetScrollPos (hWnd, SB_VERT, pos, TRUE); break; } } /***************************************************** @func void | vGotoCredits | Sets media view to the credits topic and sets up scrolling. @parm HWND | hWnd | Handle to the scrolling window. @rdesc Nothing. */ void vGotoCredits(HWND hWnd, DWORD dwTopicID) { VA va; RECT rect; ERR err; POINT ptScroll; int nScrollMin, nScrollMax; BOOL fBogus = FALSE; BOOL fScrollChange = FALSE; LPMV lpMV = (LPMV)GetWindowLong(hWnd, GWL_LPCREDITMV); DPF("Entered vGotoCredits\n"); if( !lpMV ) return; DPF4("vGotoCredits ..."); va = vaMVConvertHash(ghCreditTitle, dwTopicID); // if( va.dword == vaNil ) // I don't understand the construct above. va is a DWORD not a struct if (va == vaNil) { fBogus = TRUE; goto NEWMV_UPDATE; } if( !fMVSetAddress(lpMV, va, 1, 0L, (LPERR)&err) ) { DPF("Couldn't set media view address\n"); fBogus = TRUE; goto NEWMV_UPDATE; } GetClientRect(hWnd, &rect); if( !fMVRealize(lpMV, (LPRECT)&rect, (LPERR)&err) ) { DPF("Couldn't realize media view topic\n"); fBogus = TRUE; } // initialize credits' font ONCE // unfortunately, there's no one place where we realize // our MV DC, and the credits and visor can be opened // before the gadget (where we usually set the magnification) - // so this is necessarily redundant if (!gfCreditsMagSet) { HDC hDC = GetDC(NULL); if (hDC) { int iLogPix = GetDeviceCaps(hDC, LOGPIXELSY); ReleaseDC(NULL, hDC); if (iLogPix != SMALL_FONT_DY) { DPF("vSetMagnificationFactor: Adjusting font size... (%i)\n", (SMALL_FONT_DY * 100) / iLogPix); if (!fMVSetMagnifier(lpMV, (SMALL_FONT_DY * 100) / iLogPix, &err)) { DPF("vSetMagnificationFactor: Couldn't set magnifier (err = %u)\n", err); } } } gfCreditsMagSet = TRUE; } NEWMV_UPDATE: // // Set up the vertical scrollbar. // if ( !fBogus ) { ptScroll = ptMVGetScrollSizes(lpMV); if( ptScroll.y == 0 ) { GetScrollRange(hWnd, SB_VERT, &nScrollMin, &nScrollMax); if ( (nScrollMax - nScrollMin) > 0 ) fScrollChange = TRUE; SetScrollRange(hWnd, SB_VERT, 0, 0, FALSE); SetScrollPos(hWnd, SB_VERT, 0, TRUE); } else { GetScrollRange(hWnd, SB_VERT, &nScrollMin, &nScrollMax); if ( (nScrollMax - nScrollMin) == 0 || GetScrollPos(hWnd, SB_VERT) != 1 ) fScrollChange = TRUE; SetScrollRange(hWnd, SB_VERT, 1, ptScroll.y, FALSE); SetScrollPos(hWnd, SB_VERT, 1, TRUE); } // We need to re-realize the content with the new client rect size if // the scrollbar status changes. if (fScrollChange) { MVUnrealize(lpMV); GetClientRect(hWnd, &rect); fMVRealize(lpMV, (LPRECT)&rect, (LPERR)&err); } } else { SetScrollRange(hWnd, SB_VERT, 0, 0, FALSE); SetScrollPos(hWnd, SB_VERT, 0, FALSE); MVUnrealize(lpMV); DPF("MVUnrealize Called!\n"); } InvalidateRect(hWnd, NULL, TRUE); if (fScrollChange) FORWARD_WM_NCPAINT(hWnd, 0, SendMessage); } BOOL FGetFileVersion(char *szFullPath, DWORD *pdwMS, DWORD *pdwLS); /*************************************************************** @func void | vShowPID | This function display the PID number in a message box. It is assumed the PID is a raw data string in the resource file with an ID of 128. The form of the displayed PID is NNNNN-SSS-XXXXXXX. @rdesc None. ******************************************************************/ void _loadds WINAPI vShowPid(HWND hWnd) { // REVIEW: [*****] This should be a resource string, of course. LPSTR lpszPIDDlg = "IDD_PID"; DialogBox(SenUtilState.hInst, lpszPIDDlg, hWnd, (DLGPROC)fPIDDlg); // all the text-displaying code has been moved into the dialog callback } typedef DWORD (FAR PASCAL *LPFNVIS)(char*, DWORD FAR *); typedef BOOL (FAR PASCAL *LPFNVI)(char*, DWORD, DWORD, char*); typedef BOOL (FAR PASCAL *LPFNVQV)(void FAR *, char*, void FAR * FAR *, WORD FAR *); /* This function was stolen from \sendak\dev\newsetup\common\win\detwin.c ** ** ** Purpose: ** Gets the file version values from the given file and sets the ** given pdwMS/pdwLS variables. ** Arguments: ** szFullPath: a zero terminated character string containing the fully ** qualified path (including disk drive) to the file. ** pdwMS: Most significant 32 bits of source file version stamp. ** pdwLS: Least significant 32 bits of source file version stamp. ** Returns: ** TRUE if file and file version resource found and retrieved, ** FALSE if not. **************************************************************************/ BOOL FGetFileVersion(char *szFullPath, DWORD *pdwMS, DWORD *pdwLS) { VS_FIXEDFILEINFO * pvsfi; DWORD dwHandle; UINT cbLen; BOOL fRet = FALSE; DWORD cbBuf = 2*sizeof(WORD) + 28*sizeof(char*) + sizeof(VS_FIXEDFILEINFO); BYTE rgbBuf[2*sizeof(WORD) + 28*sizeof(char*) + sizeof(VS_FIXEDFILEINFO)]; // REVIEW: We should be using the ver.lib and version.lib import libraries instead // of dynamically linking like this. /* ------------------------------------------------------------------------ LPFNVIS lpfnVIS; LPFNVI lpfnVI; LPFNVQV lpfnVQV; HINSTANCE hinstDLL; if ((hinstDLL = LoadLibrary("VER.DLL")) == 0) return(FALSE); if ((int)hinstDLL < 32) return(FALSE); lpfnVIS = (LPFNVIS)GetProcAddress(hinstDLL,"GetFileVersionInfoSize"); lpfnVI = (LPFNVI)GetProcAddress(hinstDLL,"GetFileVersionInfo"); lpfnVQV = (LPFNVQV)GetProcAddress(hinstDLL,"VerQueryValue"); if (lpfnVIS == NULL || lpfnVI == NULL || lpfnVQV == NULL) { fRet = FALSE; } if ((*lpfnVIS)(szFullPath, &dwHandle) != NULL && (*lpfnVI)(szFullPath, dwHandle, cbBuf, (char*)rgbBuf) && (*lpfnVQV)((void FAR *)rgbBuf, (char*)"\\", (void FAR * FAR *)&pvsfi, (WORD FAR *)&cbLen)) ------------------------------------------------------------------------ */ // And now we do if (GetFileVersionInfoSize(szFullPath, &dwHandle) != NULL && GetFileVersionInfo(szFullPath, dwHandle, cbBuf, (char *)rgbBuf) && VerQueryValue((void FAR *)rgbBuf, (char *)"\\", (void FAR * FAR *)&pvsfi, (UINT FAR *)&cbLen)) { *pdwMS = pvsfi->dwFileVersionMS; *pdwLS = pvsfi->dwFileVersionLS; fRet = TRUE; } else { fRet = FALSE; } //FreeLibrary(hinstDLL); return(fRet); } /******************************************************************/ /* @doc EXTERNAL @func void | CreditsWnd_OnKey | Handles key-down messages @parm HWND | hwnd | window getting the message @parm UINT | vk | keycode @rdesc nothing */ void CreditsWnd_OnKey(HWND hwnd, UINT vk, BOOL, int, UINT) { if (vk == 'I' && GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) < 0) { vShowPid(hwnd); } } /******************************************************************/ /* @doc EXTERNAL @func BOOL | fPIDDlg | Dialog box window procedure for the PID dialog @parm HWND | hWnd | Handle to this dialog box. @parm UINT | msg | Message for this dialog box. @parm WPARAM | wParam | WPARAM, message dependent. @parm LPARAM | lParam | LPARAM, message dependent. @resdc Message dependent. */ BOOL CALLBACK _loadds fPIDDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { static DWORD dwVersionMS; static DWORD dwVersionLS; switch (msg) { case WM_INITDIALOG: { // Get the version info straight from the dll's rc version stamp LPSENSTATE lpSenState = lpGetSenState(); char szPathname[132]; // longest ini entry we accept is 120 plus 11 for explora.ini and 1 for \0 RECT rcSpam; RECT rcClient; GetWindowRect(lpSenState->hMattWnd, &rcSpam); GetClientRect(hWnd, &rcClient); // center the dialog box in the middle of the SPAM window MoveWindow(hWnd, (rcSpam.left + rcSpam.right) / 2 - (rcClient.right) / 2, (rcSpam.top + rcSpam.bottom) / 2 - (rcClient.bottom) / 2, rcClient.right, rcClient.bottom + GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYDLGFRAME), FALSE); // Localize: The explora.dll name should change for each language (eg. exploraz.dll for UK English) // ToDo: This name should be in a string table // WIN32: name changed #ifdef WIN32 char rgchDllName[MAX_STRLEN]; if (LoadString(lpSenState->hInst, STR_SHAREDDLLNAME, rgchDllName, MAX_STRLEN)) { GetSystemDirectory(szPathname, 132); lstrcat(szPathname, "\\"); lstrcat(szPathname, (LPSTR)rgchDllName); } #else lstrcpy(szPathname, lpSenState->lpszInstPath); lstrcat(szPathname, "explor16.dll"); #endif if (!(FGetFileVersion(szPathname, &dwVersionMS, &dwVersionLS))) { // if we fail to get the file version from the rc stamp, use the slm rmj values // ToDo: if we increment the version number, this value will need to be incr as well dwVersionMS = (1 << 16) + rmj; } } return TRUE; // WIN32: New message is used, with same functionality as Win16 #ifdef WIN32 case WM_CTLCOLORDLG: #else case WM_CTLCOLOR: if (HIWORD(lParam) == CTLCOLOR_DLG) #endif return (BOOL)GetStockObject(LTGRAY_BRUSH); case WM_PAINT: { PAINTSTRUCT ps; LPSENSTATE lpSenState = lpGetSenState(); LPSTR lpszAboutRes; LPSTR lpszPid; char rgchVersion[MAX_STRLEN], rgchTitle[MAX_STRLEN]; LPSTR lpszOutput; LPSTR lpsz; RECT rcClient; int iCount; HFONT hFont; BeginPaint(hWnd, &ps); // Create the font we will use! HLOCAL hLocal = LocalAlloc(LPTR, sizeof(LOGFONT)); if ( hLocal ) { PLOGFONT plfont = (PLOGFONT)LocalLock(hLocal); if ( plfont ) { plfont->lfHeight = -12; strcpy(plfont->lfFaceName, "Arial"); hFont = CreateFontIndirect(plfont); LocalUnlock(hLocal); LocalFree(hLocal); } } HFONT hOldFont = NULL; if ( hFont ) { hOldFont = (HFONT)SelectObject(ps.hdc, hFont); } SetBkMode(ps.hdc, TRANSPARENT); SetTextColor(ps.hdc, RGB(0, 0, 0)); /* Format of resources: RC_ABOUT_BOX: Title\n\n Copyright\n\n Product ID: %s\n\n Text RC_PID_NUMBER(Win16) 12345-123-1234567 RC_PID_NUMBER(Win32) Garbage for 128 bytes RPC -> 12345 Site -> 123 Serial-> 1234567 Random-> 12345 STBL_VERSION Version %u.%u We want the PID to look like 12345-123-1234567-12345 for Win32 (23 characters - PID 2.0 spec) We want the PID to look like 12345-123-1234567 for Win16 (17 characters - PID 1.0 spec) Dialog should look like: Title Version Copyright Product ID Text */ if(LoadString(lpSenState->hInst, STR_TITLE, rgchTitle, MAX_STRLEN)) { /* this is here because Win95 and NT 3.51 will not load the resource after the first '\n' if you alt+tab away and back. So we have '\t's in the resource and replace them with '\n's after the resource has been loaded. */ lpszAboutRes = (LPSTR)LoadGenResource(lpSenState->hInst, MAKEINTRESOURCE(RC_ABOUT_BOX), RT_RCDATA); if (lpszAboutRes) { lpszPid = (LPSTR)LoadGenResource(lpSenState->hInst, MAKEINTRESOURCE(RC_PID_NUMBER), RT_RCDATA); if(lpszPid) { if (LoadString(SenUtilState.hInst, STBL_VERSION, rgchVersion, MAX_STRLEN)) { #ifdef WIN32 lpszOutput = (LPSTR)GlobalAllocPtr(GMEM_MOVEABLE, lstrlen(lpszAboutRes) + lstrlen(rgchVersion) + 10 + 23); #else // Win16 lpszOutput = (LPSTR)GlobalAllocPtr(GMEM_MOVEABLE, lstrlen(lpszAboutRes) + lstrlen(rgchVersion) + 10 + lstrlen(lpszPid)); #endif if(lpszOutput) { //for(iCount=0 ; (lpszAboutRes[iCount]) && (lpszAboutRes[iCount] != '\n') ; iCount++); iCount = lstrlen(rgchTitle); // need one little '+ 1' in here and it works perfectly lstrcpyn(lpszOutput, rgchTitle, iCount + 1); // Put title into output buffer (terminated with \0) SetWindowText(hWnd, lpszOutput); // use output buffer to set window's caption lpsz = lpszOutput + iCount; // calculate the append point of the output buffer *lpsz++ = '\n'; // add a carriage return to output buffer (end of 1st line) lpsz += wsprintf(lpsz, // append to the output buffer rgchVersion, // the version info line HIWORD(dwVersionMS), // Major version # LOWORD(dwVersionMS)); // Minor version # #ifdef WIN32 #define PID_RPC 128 #define PID_SITE (PID_RPC + 5) #define PID_SERIAL (PID_SITE + 3) #define PID_RANDOM (PID_SERIAL + 7) wsprintf(rgchVersion, // In Win32 we must format the PID ourselves "%5.5s-%3.3s-%7.7s-%5.5s", lpszPid+PID_RPC, lpszPid+PID_SITE, lpszPid+PID_SERIAL, lpszPid+PID_RANDOM); UnloadGenResource(lpszPid, FALSE); // we're done with the resource we loaded now lpszPid = rgchVersion; // fake out following Win16 code to display formated pid #endif wsprintf(lpsz, // append the rest of the about box to the output string lpszAboutRes+iCount, lpszPid); // passing in the PID # string to be inserted in the %s #ifndef WIN32 UnloadGenResource(lpszPid, FALSE); // If we're Win16 we need to unload the PID resource now #endif // paint the output GetClientRect(hWnd, &rcClient); rcClient.left += 15; rcClient.right -= 30; rcClient.top += 15; rcClient.bottom -= 30; DrawText(ps.hdc, lpszOutput, -1, &rcClient, DT_LEFT | DT_WORDBREAK); GlobalFreePtr(lpszOutput); } // if alloc lpszOutput } // if loaded version string } // if loaded lpszPid UnloadGenResource(lpszAboutRes, FALSE); } } // if loaded lpszAboutRes if ( hFont ) { hOldFont = (HFONT)SelectObject(ps.hdc, hFont); DeleteObject(hFont); } EndPaint(hWnd, &ps); return TRUE; } case WM_COMMAND: switch(LOWORD(wParam)) // works for both Win16 and Win32 { case IDOK: EndDialog(hWnd, TRUE); break; case IDD_PIDINFO: { char rgchMSInfo[128]; LPSTR lpsz; lstrcpy((LPSTR)rgchMSInfo, lpGetSenState()->lpszMMIOPath); lpsz = (LPSTR)rgchMSInfo; lpsz += lstrlen(lpsz); while (*lpsz != '\\' && lpsz != (LPSTR)rgchMSInfo) { lpsz--; } // if we have reached the beginning of the buffer, something is wrong. screw it *lpsz = '\0'; #ifdef WIN32 lstrcat((LPSTR)rgchMSInfo, "\\WINSYS\\MSINFO32.EXE"); #else lstrcat((LPSTR)rgchMSInfo, "\\WINSYS\\MSINFO.EXE"); #endif EndDialog(hWnd, TRUE); WinExec((LPSTR)rgchMSInfo, SW_SHOWNORMAL); } break; } return TRUE; } return FALSE; }