330 lines
7.8 KiB
C
330 lines
7.8 KiB
C
/*************************************************************************
|
|
**
|
|
** OLE 2 Sample Code
|
|
**
|
|
** debug2.c
|
|
**
|
|
** This file contains various debug / subclass routines for the
|
|
** ABOUT dialog
|
|
**
|
|
** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
|
|
**
|
|
*************************************************************************/
|
|
|
|
#include "outline.h"
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
extern LPOUTLINEAPP g_lpApp;
|
|
|
|
LONG CALLBACK EXPORT DebugAbout(HWND hWnd, unsigned uMsg, WORD wParam, LONG lParam);
|
|
void RandomizeStars(HDC hDC);
|
|
BOOL InitStrings(void);
|
|
BOOL DrawString(int iCount, HDC hDC, LPRECT rcDrawIn);
|
|
|
|
static FARPROC lpRealAboutProc = 0L;
|
|
static int width, height;
|
|
static RECT rc;
|
|
static HANDLE hStrBlock = NULL;
|
|
static LPSTR lpStrings = NULL;
|
|
static WORD wLineHeight;
|
|
|
|
|
|
/* TraceDebug
|
|
* ----------
|
|
*
|
|
* Called once when our About Box's gets the INITDIALOG message. Subclasses
|
|
* dialog.
|
|
*/
|
|
|
|
void TraceDebug(HWND hDlg, int iControl)
|
|
{
|
|
|
|
// Load strings, if the strings aren't there, then don't subclass
|
|
// the dialog
|
|
if (InitStrings() != TRUE)
|
|
return;
|
|
|
|
// Subclass the dialog
|
|
lpRealAboutProc = (FARPROC)(LONG_PTR)GetWindowLongPtr(hDlg, GWLP_WNDPROC);
|
|
SetWindowLongPtr(hDlg, GWLP_WNDPROC, (LONG_PTR)(FARPROC)DebugAbout);
|
|
|
|
// Get rect of control in screen coords, and translate to our dialog
|
|
// box's coordinates
|
|
GetWindowRect(GetDlgItem(hDlg, iControl), &rc);
|
|
MapWindowPoints(NULL, hDlg, (LPPOINT)&rc, 2);
|
|
|
|
width = rc.right - rc.left;
|
|
height = rc.bottom - rc.top;
|
|
}
|
|
|
|
/* DebugAbout
|
|
* ----------
|
|
*
|
|
* The subclassed About dialog's main window proc.
|
|
*/
|
|
|
|
LONG CALLBACK EXPORT DebugAbout(HWND hWnd, unsigned uMsg, WORD wParam, LONG lParam)
|
|
{
|
|
RECT rcOut;
|
|
static BOOL bTimerStarted = FALSE;
|
|
static int iTopLocation;
|
|
HDC hDCScr;
|
|
static HDC hDCMem;
|
|
static HBITMAP hBitmap;
|
|
static HBITMAP hBitmapOld;
|
|
static RECT rcMem;
|
|
static HFONT hFont;
|
|
|
|
switch (uMsg)
|
|
{
|
|
|
|
/*
|
|
* If we get a LBUTTONDBLCLICK in the upper left of
|
|
* the dialog, fire off the about box effects
|
|
*/
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
if ((wParam & MK_CONTROL) && (wParam & MK_SHIFT)
|
|
&& LOWORD(lParam) < 10 && HIWORD(lParam) < 10 &&
|
|
bTimerStarted == FALSE)
|
|
{
|
|
if (SetTimer ( hWnd, 1, 10, NULL ))
|
|
{
|
|
LOGFONT lf;
|
|
int i;
|
|
|
|
bTimerStarted = TRUE;
|
|
|
|
// "Open up" the window
|
|
hDCScr = GetDC ( hWnd );
|
|
hDCMem = CreateCompatibleDC ( hDCScr );
|
|
|
|
hBitmap = CreateCompatibleBitmap(hDCScr, width, height);
|
|
hBitmapOld = SelectObject(hDCMem, hBitmap);
|
|
|
|
// Blt from dialog to memDC
|
|
BitBlt(hDCMem, 0, 0, width, height,
|
|
hDCScr, rc.left, rc.top, SRCCOPY);
|
|
|
|
for (i=0;i<height;i+=1)
|
|
{
|
|
BitBlt(hDCScr, rc.left, rc.top + i + 1, width, height-i-1, hDCMem, 0, 0, SRCCOPY);
|
|
PatBlt(hDCScr, rc.left, rc.top + i, width, 1, BLACKNESS);
|
|
}
|
|
|
|
SelectObject(hDCMem, hBitmapOld);
|
|
DeleteObject(hBitmap);
|
|
|
|
// Set up memory DC with default attributes
|
|
hBitmap = CreateCompatibleBitmap(hDCScr, width, height);
|
|
ReleaseDC(hWnd, hDCScr);
|
|
|
|
hBitmapOld = SelectObject(hDCMem, hBitmap);
|
|
|
|
SetBkMode(hDCMem, TRANSPARENT);
|
|
SetBkColor(hDCMem, RGB(0,0,0));
|
|
|
|
// Create font
|
|
memset(&lf, 0, sizeof(LOGFONT));
|
|
lf.lfHeight = -(height / 7); // Fit 7 lines of text in box
|
|
lf.lfWeight = FW_BOLD;
|
|
strcpy(lf.lfFaceName, "Arial");
|
|
hFont = CreateFontIndirect(&lf);
|
|
|
|
// If we can't create the font, revert and use the standard
|
|
// system font.
|
|
if (!hFont)
|
|
GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), &lf);
|
|
|
|
wLineHeight = abs(lf.lfHeight) + 5; // 5 pixels between lines
|
|
|
|
// Set location of top of banner at bottom of the window
|
|
iTopLocation = height + 50;
|
|
|
|
SetRect(&rcMem, 0, 0, width, height);
|
|
}
|
|
}
|
|
// Call our real window procedure in case they want to
|
|
// handle LBUTTONDOWN messages also
|
|
goto Default;
|
|
|
|
case WM_TIMER:
|
|
{
|
|
int iCount;
|
|
HFONT hfold;
|
|
|
|
/*
|
|
* On each timer message, we are going to construct the next image
|
|
* in the animation sequence, then bitblt this to our dialog.
|
|
*/
|
|
|
|
// Clear out old bitmap and place random star image on background
|
|
PatBlt(hDCMem, rcMem.left, rcMem.top, rcMem.right, rcMem.bottom, BLACKNESS);
|
|
RandomizeStars(hDCMem);
|
|
|
|
// Set initial location to draw text
|
|
rcOut = rcMem;
|
|
rcOut.top = 0 + iTopLocation;
|
|
rcOut.bottom = rcOut.top + wLineHeight;
|
|
|
|
iCount = 0;
|
|
if (hFont) hfold = SelectObject(hDCMem, hFont);
|
|
|
|
SetTextColor(hDCMem, RGB(0,255,0));
|
|
while (DrawString(iCount, hDCMem, &rcOut) == TRUE)
|
|
{
|
|
rcOut.top += wLineHeight;
|
|
rcOut.bottom += wLineHeight;
|
|
iCount++;
|
|
}
|
|
if (hFont) SelectObject(hDCMem, hfold);
|
|
|
|
// Now blt the memory dc that we have just constructed
|
|
// to the screen
|
|
hDCScr = GetDC(hWnd);
|
|
BitBlt(hDCScr, rc.left, rc.top, rc.right, rc.bottom,
|
|
hDCMem, 0, 0, SRCCOPY);
|
|
ReleaseDC(hWnd, hDCScr);
|
|
|
|
// For the next animation sequence, we want to move the
|
|
// whole thing up, so decrement the location of the top
|
|
// of the banner
|
|
|
|
iTopLocation -= 2;
|
|
|
|
// If we've gone through the banner once, reset it
|
|
if (iTopLocation < -(int)(wLineHeight * iCount))
|
|
iTopLocation = height + 50;
|
|
}
|
|
// Goto default
|
|
goto Default;
|
|
|
|
case WM_NCDESTROY:
|
|
{
|
|
LONG defReturn;
|
|
|
|
/*
|
|
* We're being destroyed. Clean up what we created.
|
|
*/
|
|
|
|
if (bTimerStarted)
|
|
{
|
|
KillTimer(hWnd, 1);
|
|
SelectObject (hDCMem, hBitmapOld);
|
|
DeleteObject (hBitmap);
|
|
DeleteDC (hDCMem);
|
|
if (hFont) DeleteObject(hFont);
|
|
bTimerStarted = FALSE;
|
|
}
|
|
|
|
if (lpStrings)
|
|
UnlockResource(hStrBlock), lpStrings = NULL;
|
|
if (hStrBlock)
|
|
FreeResource(hStrBlock), hStrBlock = NULL;
|
|
|
|
// Pass the NCDESTROY on to our real window procedure. Since
|
|
// this is the last message that we are going to be getting,
|
|
// we can go ahead and free the proc instance here.
|
|
|
|
defReturn = CallWindowProc((WNDPROC)lpRealAboutProc, hWnd,
|
|
uMsg, wParam, lParam);
|
|
return defReturn;
|
|
}
|
|
|
|
Default:
|
|
default:
|
|
return CallWindowProc(
|
|
(WNDPROC)lpRealAboutProc, hWnd, uMsg, wParam, lParam);
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
|
|
/* RandomizeStars
|
|
* --------------
|
|
*
|
|
* Paints random stars on the specified hDC
|
|
*
|
|
*/
|
|
|
|
void RandomizeStars(HDC hDC)
|
|
{
|
|
int i;
|
|
|
|
// Seed the random number generator with current time. This will,
|
|
// in effect, only change the seed every second, so our
|
|
// starfield will change only every second.
|
|
srand((unsigned)time(NULL));
|
|
|
|
// Generate random white stars
|
|
for (i=0;i<20;i++)
|
|
PatBlt(hDC, getrandom(0,width), getrandom(0,height), 2, 2, WHITENESS);
|
|
}
|
|
|
|
/* InitStrings
|
|
* --------------
|
|
*
|
|
* Reads strings from stringtable. Returns TRUE if it worked OK.
|
|
*
|
|
*/
|
|
|
|
BOOL InitStrings()
|
|
{
|
|
HRSRC hResStrings;
|
|
LPSTR lpWalk;
|
|
|
|
// Load the block of strings
|
|
if ((hResStrings = FindResource(
|
|
g_lpApp->m_hInst,
|
|
MAKEINTRESOURCE(9999),
|
|
RT_RCDATA)) == NULL)
|
|
return FALSE;
|
|
if ((hStrBlock = LoadResource(g_lpApp->m_hInst, hResStrings)) == NULL)
|
|
return FALSE;
|
|
if ((lpStrings = LockResource(hStrBlock)) == NULL)
|
|
return FALSE;
|
|
|
|
if (lpStrings && *(lpStrings+2)!=0x45)
|
|
{
|
|
lpWalk = lpStrings;
|
|
while (*(LPWORD)lpWalk != (WORD)0x0000)
|
|
{
|
|
if (*lpWalk != (char)0x00)
|
|
*lpWalk ^= 0x98;
|
|
lpWalk++;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* DrawString
|
|
* ----------
|
|
*
|
|
* Draws the next string on the specified hDC using the
|
|
* output rectangle. If iCount == 0, reset to start of list.
|
|
*
|
|
* Returns: TRUE to contine, FALSE if we're done
|
|
*/
|
|
|
|
BOOL DrawString(int iCount, HDC hDC, LPRECT rcDrawIn)
|
|
{
|
|
static LPSTR lpPtr = NULL;
|
|
|
|
if (iCount == 0)
|
|
// First time, reset pointer
|
|
lpPtr = lpStrings;
|
|
|
|
if (*lpPtr == '\0') // If we've hit a NULL string, we're done
|
|
return FALSE;
|
|
|
|
// If we're drawing outside of visible box, don't call DrawText
|
|
if ((rcDrawIn->bottom > 0) && (rcDrawIn->top < height))
|
|
DrawText(hDC, lpPtr, -1, rcDrawIn, DT_CENTER);
|
|
|
|
// Advance pointer to next string
|
|
lpPtr += lstrlen(lpPtr) + 1;
|
|
|
|
return TRUE;
|
|
}
|