windows-nt/Source/XPSP1/NT/multimedia/media/cdplayer/ledwnd.c
2020-09-26 16:20:57 +08:00

842 lines
19 KiB
C

/******************************Module*Header*******************************\
* Module Name: ledwnd.c
*
* Implementation of the LED window.
*
*
* Created: 18-11-93
* Author: Stephen Estrop [StephenE]
*
* Copyright (c) 1993 Microsoft Corporation
\**************************************************************************/
#pragma warning( once : 4201 4214 )
#define NOOLE
#include <windows.h> /* required for all Windows applications */
#include <windowsx.h>
#include <string.h>
#include <tchar.h> /* contains portable ascii/unicode macros */
#include "resource.h"
#include "cdplayer.h"
#include "cdapi.h"
#include "buttons.h"
#include "literals.h"
#define DECLARE_DATA
#include "ledwnd.h"
/* -------------------------------------------------------------------------
** Private functions for the LED class
** -------------------------------------------------------------------------
*/
BOOL
LED_OnCreate(
HWND hwnd,
LPCREATESTRUCT lpCreateStruct
);
void
LED_OnPaint(
HWND hwnd
);
void
LED_OnLButtonUp(
HWND hwnd,
int x,
int y,
UINT keyFlags
);
void
LED_OnRButtonUp(
HWND hwnd,
int x,
int y,
UINT keyFlags
);
void
LED_OnSetText(
HWND hwnd,
LPCTSTR lpszText
);
void
LED_DrawText(
HWND hwnd,
LPCTSTR s,
int sLen
);
void
LED_CreateLEDFonts(
HDC hdc
);
/******************************Public*Routine******************************\
* InitLEDClass
*
* Called to register the LED window class and create a font for the LED
* window to use. This function must be called before the CD Player dialog
* box is created.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
InitLEDClass(
HINSTANCE hInst
)
{
WNDCLASS LEDwndclass;
HDC hdc;
ZeroMemory( &LEDwndclass, sizeof(LEDwndclass) );
/*
** Register the LED window.
*/
LEDwndclass.lpfnWndProc = LEDWndProc;
LEDwndclass.hInstance = hInst;
LEDwndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
LEDwndclass.hbrBackground = GetStockObject( BLACK_BRUSH );
LEDwndclass.lpszClassName = g_szLEDClassName;
LEDwndclass.style = CS_OWNDC;
hdc = GetDC( GetDesktopWindow() );
LED_CreateLEDFonts( hdc );
ReleaseDC( GetDesktopWindow(), hdc );
return RegisterClass( &LEDwndclass );
}
/******************************Public*Routine******************************\
* LEDWndProc
*
* This routine handles the WM_PAINT and WM_SETTEXT messages
* for the "LED" display window.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
LRESULT CALLBACK
LEDWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
switch( message ) {
HANDLE_MSG( hwnd, WM_CREATE, LED_OnCreate );
HANDLE_MSG( hwnd, WM_PAINT, LED_OnPaint );
HANDLE_MSG( hwnd, WM_LBUTTONUP, LED_OnLButtonUp );
HANDLE_MSG( hwnd, WM_RBUTTONUP, LED_OnRButtonUp );
HANDLE_MSG( hwnd, WM_SETTEXT, LED_OnSetText );
}
return DefWindowProc( hwnd, message, wParam, lParam );
}
/*****************************Private*Routine******************************\
* LED_OnCreate
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
LED_OnCreate(
HWND hwnd,
LPCREATESTRUCT lpCreateStruct
)
{
HDC hdcLed;
hdcLed = GetDC( hwnd );
SelectObject( hdcLed, g_fSmallLedFont ? hLEDFontS : hLEDFontL );
SetTextColor( hdcLed, RGB(0x80,0x80,0x00) );
ReleaseDC( hwnd, hdcLed );
return TRUE;
}
/*****************************Private*Routine******************************\
* LED_OnPaint
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
LED_OnPaint(
HWND hwnd
)
{
PAINTSTRUCT ps;
TCHAR s[50];
int sLen;
RECT rcLed;
HDC hdcLed;
hdcLed = BeginPaint( hwnd, &ps );
#ifdef DAYTONA
/*
** For some (unknown) reason Daytona does not redraw the
** screen correctly after the screen save has exited. Chicago does !!
*/
DefWindowProc( hwnd, WM_ERASEBKGND, (WPARAM)hdcLed, 0 );
#endif
GetClientRect( hwnd, &rcLed );
sLen = GetWindowText( hwnd, s, 50 );
/*
** Draw the LED display text
*/
LED_DrawText( hwnd, s, sLen );
/*
** Draw a shaded frame around the LED display
*/
DrawEdge( hdcLed, &rcLed, EDGE_SUNKEN, BF_RECT );
EndPaint( hwnd, &ps );
}
/*****************************Private*Routine******************************\
* LED_OnLButtonUp
*
* Rotate the time remaing buttons and then set the display accordingly.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
LED_OnLButtonUp(
HWND hwnd,
int x,
int y,
UINT keyFlags
)
{
BOOL b;
/*
** If this window is not the master display LED just return
*/
if ( GetWindowLong(hwnd, GWL_ID) != IDC_LED ) {
return;
}
b = g_fDisplayDr;
g_fDisplayDr = g_fDisplayTr;
g_fDisplayTr = g_fDisplayT;
g_fDisplayT = b;
UpdateToolbarTimeButtons();
UpdateDisplay( DISPLAY_UPD_LED );
}
/*****************************Private*Routine******************************\
* LED_OnRButtonUp
*
* Determine if we should do something interesting with the LED display.
*
* History:
* dd-mm-94 - StephenE - Created
*
\**************************************************************************/
void
LED_OnRButtonUp(
HWND hwnd,
int x,
int y,
UINT keyFlags
)
{
DWORD dwTime;
static DWORD dwTimeSave;
extern BOOL g_fTitlebarShowing;
/*
** If we are in mini mode and there is no cd loaded and the Shift and
** control keys are down and it is more than 500 ms and less than 1500 ms
** since an identical sequence was performed then display the credits.
*/
if ( !g_fTitlebarShowing && (g_State & CD_NO_CD) ) {
dwTime = GetCurrentTime();
switch ( keyFlags & (MK_SHIFT | MK_CONTROL) ) {
case (MK_SHIFT | MK_CONTROL):
dwTimeSave = dwTime;
break;
case 0:
if ( (dwTime - dwTimeSave) > 500 && (dwTime - dwTimeSave) < 1500 ) {
void DoC(HWND hwnd);
DoC( hwnd );
}
break;
}
}
}
/*****************************Private*Routine******************************\
* DoC
*
* Do interesting things to the LED display
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
DoC(
HWND hwnd
)
{
RECT rc;
RECT rcUpdate;
HDC hdc;
MSG msg;
int dyLine;
int yLine;
TEXTMETRIC tm;
DWORD dwNextTime;
long lScroll;
DWORD rgb;
HWND hwndFocusSave;
LPSTR pchSrc, pchDst;
char achLine[100];
int iEncrypt;
const int dxEdge = 2, dyEdge = 2;
#define EOFCHAR '@' // end of stream
pchSrc = &cr[0];
/* we want to get all mouse and keyboard events, to make
** sure we stop the animation when the user clicks or
** hits a key
*/
hwndFocusSave = SetFocus(hwnd);
SetCapture(hwnd);
/* Scroll the crs up, one pixel at a time. pchSrc
** points to the encrypted data; achLine contains a decrypted
** line (null-terminated). dyLine is the height of each
** line (constant), and yLine is between 0 and dyLine,
** indicating how many pixels of the line have been scrolled
** in vertically from the bottom
*/
hdc = GetDC(hwnd);
SaveDC(hdc);
SelectObject(hdc, GetStockObject(ANSI_VAR_FONT));
GetClientRect(hwnd, &rc);
SetTextAlign(hdc, TA_CENTER);
SetBkColor(hdc, RGB(0, 0, 0));
SetRect(&rcUpdate, dxEdge, rc.bottom - (dyEdge + 1),
rc.right - dxEdge, rc.bottom - dyEdge);
GetTextMetrics(hdc, &tm);
if ((dyLine = tm.tmHeight + tm.tmExternalLeading) == 0) {
dyLine = 1;
}
yLine = dyLine;
dwNextTime = GetCurrentTime(); // time to do the next scroll
lScroll = 0;
iEncrypt = 0;
for ( ;; ) {
/*
** If the user clicks the mouse or hits a key, exit.
*/
if (PeekMessage( &msg, hwnd, WM_KEYFIRST, WM_KEYLAST,
PM_NOREMOVE | PM_NOYIELD)) {
break; // exit on key hit
}
if (PeekMessage(&msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
PM_NOREMOVE | PM_NOYIELD)) {
if ( (msg.message == WM_MOUSEMOVE) ||
(msg.message == WM_NCMOUSEMOVE) ) {
/* remove and ignore message */
PeekMessage(&msg, hwnd, msg.message, msg.message,
PM_REMOVE | PM_NOYIELD);
}
else {
break; // exit on click
}
}
/* scroll at a fixed no. of vertical pixels per sec. */
if (dwNextTime > GetCurrentTime()) {
continue;
}
dwNextTime += 50L; // millseconds per scroll
if (yLine == dyLine) {
/* decrypt a line and copy to achLine */
pchDst = achLine;
while (TRUE) {
*pchDst = (char)(*pchSrc++ ^(128 | (iEncrypt++ & 127)));
if ((*pchDst == '\r') || (*pchDst == EOFCHAR)) {
break;
}
pchDst++;
}
if (*pchDst == EOFCHAR) {
break; // no more lines
}
*pchDst = 0; // null-terminate
pchSrc++, iEncrypt++; // skip '\n'
yLine = 0;
}
/* scroll screen up one pixel */
BitBlt( hdc, dxEdge, dyEdge,
rcUpdate.right - dxEdge, rcUpdate.top - dxEdge,
hdc, dxEdge, dyEdge + 1, SRCCOPY);
/* vary the text colors through a "rainbow" */
switch ( (int)(lScroll++ / 4) % 5 ) {
case 0: rgb = RGB(255, 0, 0); break;
case 1: rgb = RGB(255, 255, 0); break;
case 2: rgb = RGB( 0, 255, 0); break;
case 3: rgb = RGB( 0, 255, 255); break;
case 4: rgb = RGB(255, 0, 255); break;
}
SetTextColor(hdc, rgb);
/* fill in the bottom pixel */
SaveDC(hdc);
yLine++;
IntersectClipRect(hdc, rcUpdate.left, rcUpdate.top,
rcUpdate.right, rcUpdate.bottom);
ExtTextOutA(hdc, rc.right / 2, rc.bottom - yLine,
ETO_OPAQUE, &rcUpdate,
achLine, lstrlenA(achLine), NULL);
RestoreDC(hdc, -1);
}
RestoreDC(hdc, -1);
ReleaseDC(hwnd, hdc);
ReleaseCapture();
InvalidateRect(hwnd, NULL, TRUE);
SetFocus(hwndFocusSave);
}
/*****************************Private*Routine******************************\
* LED_ToggleDisplayFont
*
* Toggles between the large and the small display font and erases the
* background of the led display. This removes any sign of the old font.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
LED_ToggleDisplayFont(
HWND hwnd,
BOOL fFont
)
{
RECT rcLed;
HDC hdcLed;
hdcLed = GetDC( hwnd );
GetClientRect( hwnd, &rcLed );
SelectObject( hdcLed, fFont ? hLEDFontS : hLEDFontL );
ReleaseDC( hwnd, hdcLed );
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
/*****************************Private*Routine******************************\
* LED_DrawText
*
* Draws the LED display screen text (quickly). The text is centered
* vertically and horizontally. Only the backround is drawn if the g_fFlashed
* flag is set.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
LED_DrawText(
HWND hwnd,
LPCTSTR s,
int sLen
)
{
HDC hdcLed;
RECT rc;
RECT rcLed;
SIZE sz;
int xOrigin;
int yOrigin;
hdcLed = GetDC( hwnd );
GetTextExtentPoint( hdcLed, s, sLen, &sz );
GetClientRect( hwnd, &rcLed );
xOrigin = (rcLed.right - sz.cx) / 2;
yOrigin = (rcLed.bottom - sz.cy) / 2;
rc.top = yOrigin;
rc.bottom = rc.top + sz.cy;
rc.left = 2;
rc.right = rcLed.right - 3;
SetBkColor( hdcLed, RGB(0x00,0x00,0x00) );
if ( g_fFlashLed ) {
ExtTextOut( hdcLed, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
}
else {
ExtTextOut( hdcLed, xOrigin, yOrigin, ETO_OPAQUE, &rc, s, sLen, NULL);
}
ReleaseDC( hwnd, hdcLed );
}
/*****************************Private*Routine******************************\
* LED_OnSetText
*
* Change the LED display text. Calling DefWindowProc ensures that the
* window text is saved correctly.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
LED_OnSetText(
HWND hwnd,
LPCTSTR lpszText
)
{
DefWindowProc( hwnd, WM_SETTEXT, 0, (LPARAM)lpszText);
LED_DrawText( hwnd, lpszText, _tcslen(lpszText) );
}
/*****************************Private*Routine******************************\
* LED_CreateLEDFonts
*
* Small font is 12pt MS Sans Serif
* Large font is 18pt MS Sans Serif
*
* History:
* dd-mm-94 - StephenE - Created
*
\**************************************************************************/
void
LED_CreateLEDFonts(
HDC hdc
)
{
LOGFONT lf;
int iLogPelsY;
iLogPelsY = GetDeviceCaps( hdc, LOGPIXELSY );
ZeroMemory( &lf, sizeof(lf) );
lf.lfHeight = (-12 * iLogPelsY) / 72; /* 12pt */
lf.lfWeight = 700; /* bold */
lf.lfCharSet = ANSI_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = PROOF_QUALITY;
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
_tcscpy( lf.lfFaceName, g_szAppFontName );
hLEDFontS = CreateFontIndirect(&lf);
lf.lfHeight = (-18 * iLogPelsY) / 72; /* 18 pt */
lf.lfWeight = 400; /* normal */
hLEDFontL = CreateFontIndirect(&lf);
/*
** If can't create either font set up some sensible defaults.
*/
if ( hLEDFontL == NULL || hLEDFontS == NULL ) {
if ( hLEDFontL != NULL ) {
DeleteObject( hLEDFontL );
}
if ( hLEDFontS != NULL ) {
DeleteObject( hLEDFontS );
}
hLEDFontS = hLEDFontL = GetStockObject( ANSI_VAR_FONT );
}
}
/* -------------------------------------------------------------------------
** Private functions for the Text class
** -------------------------------------------------------------------------
*/
void
Text_OnPaint(
HWND hwnd
);
LRESULT CALLBACK
TextWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
);
void
Text_OnSetText(
HWND hwnd,
LPCTSTR lpszText
);
void
Text_OnSetFont(
HWND hwndCtl,
HFONT hfont,
BOOL fRedraw
);
/******************************Public*Routine******************************\
* Init_SJE_TextClass
*
* Called to register the text window class .
* This function must be called before the CD Player dialog box is created.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
Init_SJE_TextClass(
HINSTANCE hInst
)
{
WNDCLASS wndclass;
ZeroMemory( &wndclass, sizeof(wndclass) );
/*
** Register the Text window.
*/
wndclass.lpfnWndProc = TextWndProc;
wndclass.hInstance = hInst;
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wndclass.lpszClassName = g_szTextClassName;
return RegisterClass( &wndclass );
}
/******************************Public*Routine******************************\
* TextWndProc
*
* This routine handles the WM_PAINT and WM_SETTEXT messages
* for the "Text" display window.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
LRESULT CALLBACK
TextWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
switch( message ) {
HANDLE_MSG( hwnd, WM_PAINT, Text_OnPaint );
HANDLE_MSG( hwnd, WM_SETTEXT, Text_OnSetText );
HANDLE_MSG( hwnd, WM_SETFONT, Text_OnSetFont );
}
return DefWindowProc( hwnd, message, wParam, lParam );
}
/*****************************Private*Routine******************************\
* Text_OnPaint
*
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
Text_OnPaint(
HWND hwnd
)
{
PAINTSTRUCT ps;
TCHAR s[128];
int sLen;
HDC hdc;
RECT rc;
HFONT hfont;
HFONT hfontOrg;
LONG lStyle;
hdc = BeginPaint( hwnd, &ps );
GetWindowRect( hwnd, &rc );
MapWindowRect( GetDesktopWindow(), hwnd, &rc );
lStyle = GetWindowLong( hwnd, GWL_STYLE );
if ( lStyle & SS_GRAYRECT ) {
PatB( hdc, 0, 0, rc.right , 1, rgbShadow );
PatB( hdc, 0, 1, rc.right , 1, rgbHilight );
}
else {
sLen = GetWindowText( hwnd, s, 128 );
hfont = (HFONT)GetWindowLong( hwnd, GWL_USERDATA );
if ( hfont ) {
hfontOrg = SelectObject( hdc, hfont );
}
/*
** Draw a frame around the window
*/
DrawEdge( hdc, &rc, EDGE_SUNKEN, BF_RECT );
/*
** Draw the text
*/
SetBkColor( hdc, GetSysColor( COLOR_BTNFACE ) );
SetTextColor( hdc, GetSysColor( COLOR_WINDOWTEXT ) );
rc.left = 1 + (2 * GetSystemMetrics(SM_CXBORDER));
DrawText( hdc, s, sLen, &rc,
DT_NOPREFIX | DT_LEFT | DT_VCENTER |
DT_NOCLIP | DT_SINGLELINE );
if ( hfontOrg ) {
SelectObject( hdc, hfontOrg );
}
}
EndPaint( hwnd, &ps );
}
/*****************************Private*Routine******************************\
* Text_OnSetText
*
* Change the text. Calling DefWindowProc ensures that the
* window text is saved correctly.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
Text_OnSetText(
HWND hwnd,
LPCTSTR lpszText
)
{
DefWindowProc( hwnd, WM_SETTEXT, 0, (LPARAM)lpszText);
InvalidateRect( hwnd, NULL, TRUE );
UpdateWindow( hwnd );
}
/*****************************Private*Routine******************************\
* Text_OnSetFont
*
* Sets the windows font
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
Text_OnSetFont(
HWND hwnd,
HFONT hfont,
BOOL fRedraw
)
{
SetWindowLong( hwnd, GWL_USERDATA, (LONG)hfont );
if ( fRedraw ) {
InvalidateRect( hwnd, NULL, TRUE );
UpdateWindow( hwnd );
}
}