/****************************************************************************\
*
* PROGRAM: AniEdit.c
*
* PURPOSE: Animated Cursor Editor for Windows NT
*
* Copyright 1993-1996 Microsoft Corp.
*
*
* History:
* 21-Apr-1993 JonPa Wrote it.
*
\****************************************************************************/
#include <windows.h>
#include "anidefs.h"
HANDLE hInst;
HWND ghwndMain;
HWND ghwndRateScroll = NULL;
ANICUR ganiAcon;
int gcyCursor, gcxCursor;
HBRUSH ghbrPrevBackgnd, ghbrWindow, ghbrHighlight;
COLORREF gcrHighlightText;
HICON ghIcon;
TCHAR gszModPath[MAX_PATH]; /* name for above font module */
TCHAR gszWindowTitle[MAX_PATH] = TEXT("AniEdit");
TCHAR gszDots[] = TEXT("...");
PFRAME gpfrmFrames = NULL;
PCLPBRDDAT gpbdClipBoard = NULL;
TCHAR gszCursorEditor[MAX_PATH];
//HACCEL haccel;
int giradColor = 0; /* Default to desktop color */
RADIOCOLOR garadColor[] = {
{DLG_OPTIONS_RADIO_DESKCOL, COLOR_BACKGROUND},
{DLG_OPTIONS_RADIO_WINCOL, COLOR_WINDOW},
{0, 0}
};
#if DLG_OPTIONS_RADIO_DESKCOL == 0 || DLG_OPTIONS_RADIO_WINCOL == 0
# error("Dialog IDs must not equal zero!")
#endif
/*
* Registry Strings
* (Since the registry is not localized, these don't have to be read in
* from the strings RC)
*/
TCHAR gszAppKey[] = "Software\\Microsoft\\AniEdit";
TCHAR gszKeyCurEditor[] = "Editor";
TCHAR gszKeyPrevColor[] = "Preview Color";
/****************************************************************************
*
* FUNCTION: ParseCmdLine
*
* PURPOSE: Returns a pointer to the first arg of the command line
*
* History:
* 31-May-1995 JonPa Created it
*
\****************************************************************************/
TCHAR gszParseToken[MAX_PATH];
LPTSTR ParseCmdLine( int iToken ) {
LPTSTR szFile;
LPTSTR szCmdLine;
BOOL fSkipBlank;
BOOL fInQuote;
fSkipBlank = TRUE; // skip leading blanks
fInQuote = FALSE;
szFile = gszParseToken;
iToken++;
for(szCmdLine = GetCommandLine(); *szCmdLine != TEXT('\0') && iToken != 0;
szCmdLine++ ) {
switch (*szCmdLine) {
case TEXT('"'):
fInQuote = !fInQuote;
break;
case TEXT(' '):
case TEXT('\t'):
if (fInQuote) {
*szFile++ = *szCmdLine;
} else if (!fSkipBlank) {
iToken--;
*szFile++ = TEXT('\0');
szFile = gszParseToken;
fSkipBlank = TRUE;
}
break;
default:
*szFile++ = *szCmdLine;
fSkipBlank = FALSE;
break;
}
}
if (*szCmdLine == TEXT('\0') && !fSkipBlank ) {
iToken--;
*szFile++ = TEXT('\0');
}
if (iToken == 0 )
return gszParseToken;
else
return NULL;
}
/****************************************************************************
*
* FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
*
* PURPOSE: calls initialization function, processes message loop
*
* COMMENTS:
*
* Windows recognizes this function by name as the initial entry point
* for the program. This function calls the application initialization
* routine, if no other instance of the program is running, and always
* calls the instance initialization routine. It then executes a message
* retrieval and dispatch loop that is the top-level control structure
* for the remainder of execution. The loop is terminated when a WM_QUIT
* message is received, at which time this function exits the application
* instance by returning the value passed by PostQuitMessage().
*
* If this function must abort before entering the message loop, it
* returns the conventional value NULL.
*
* History:
* 21-Apr-1993 JonPa Created it
*
\****************************************************************************/
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
MSG msg; /* message */
UNREFERENCED_PARAMETER( lpCmdLine );
if (!hPrevInstance) /* Other instances of app running? */
if (!InitApplication(hInstance)) /* Initialize shared things */
return (FALSE); /* Exits if unable to initialize */
/* Perform initializations that apply to a specific instance */
if (!InitInstance(hInstance, nCmdShow))
return (FALSE);
ghIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ANI_ICON));
{ HACCEL hAccel;
HWND hwndDlg;
MSG msg;
hAccel = LoadAccelerators(hInstance, "AniEditMenu");
hwndDlg = CreateDialogParam( hInstance, MAKEINTRESOURCE(DLG_MAIN), GetDesktopWindow(),
MainWndProc, (LPARAM)ParseCmdLine(1) );
while (GetMessage(&msg, NULL, 0L, 0L))
{
if (!TranslateAccelerator(hwndDlg, hAccel, &msg))
{
if (!IsDialogMessage(hwndDlg, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
}
/* Write user profile */
WriteRegistry();
//BUGBUG - unregister preview class
if (gszModPath[0] != TEXT('\0')) {
RemoveFontResource(gszModPath);
PostMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
}
DeleteObject(ghbrPrevBackgnd);
/* Return the value from PostQuitMessage */
return (msg.wParam);
}
/****************************************************************************
*
* FUNCTION: InitApplication(HANDLE)
*
* PURPOSE: Initializes window data and registers window class
*
* COMMENTS:
*
* This function is called at initialization time only if no other
* instances of the application are running. This function performs
* initialization tasks that can be done once for any number of running
* instances.
*
* In this case, we initialize a window class by filling out a data
* structure of type WNDCLASS and calling the Windows RegisterClass()
* function. Since all instances of this application use the same window
* class, we only need to do this when the first instance is initialized.
*
*
\****************************************************************************/
BOOL InitApplication(HANDLE hInstance) /* current instance */
{
WNDCLASS cls;
/*
* Register a new window class to handle the cursor preview.
*/
cls.style = 0;
cls.lpfnWndProc = PreviewWndProc;
cls.cbClsExtra = 0;
cls.cbWndExtra = 0;
cls.hInstance = hInstance;
cls.hIcon = NULL;
cls.hCursor = NULL;
cls.hbrBackground = NULL;
cls.lpszMenuName = NULL;
cls.lpszClassName = szPREVIEW;
RegisterClass(&cls);
AniAddFontModule(hInstance);
return TRUE;
}
void AniAddFontModule(HINSTANCE hInst) {
if (GetModuleFileName(hInst, gszModPath, MAX_PATH))
AddFontResource(gszModPath);
else
gszModPath[0] = TEXT('\0');
}
/****************************************************************************
*
* FUNCTION: InitInstance(HANDLE, int)
*
* PURPOSE: Saves instance handle and creates main window
*
* COMMENTS:
*
* This function is called at initialization time for every instance of
* this application. This function performs initialization tasks that
* cannot be shared by multiple instances.
*
* In this case, we save the instance handle in a static variable and
* create and display the main program window.
*
\****************************************************************************/
BOOL InitInstance(
HANDLE hInstance,
int nCmdShow)
{
/* Save the instance handle in static variable, which will be used in */
/* many subsequence calls from this application to Windows. */
hInst = hInstance;
gcyCursor = GetSystemMetrics(SM_CYCURSOR);
gcxCursor = GetSystemMetrics(SM_CXCURSOR);
#ifdef DBCS
/* Load resource strings */
if (!LoadResourceStr())
return FALSE;
#endif
/* Load user profile */
ReadRegistry();
#if 0
/* Load the accel table */
if (!(haccel = LoadAccelerators(hInstance, "AniEditAccel")))
return FALSE;
#endif
return (TRUE); /* Returns the value from PostQuitMessage */
}
/* Copied from winfile:
*/
INT APIENTRY GetHeightFromPoints( int pts)
{
HDC hdc;
INT height;
hdc = GetDC (NULL);
height = MulDiv(-pts, GetDeviceCaps (hdc, LOGPIXELSY), 72);
ReleaseDC (NULL, hdc);
return height;
}
/****************************************************************************
*
* FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE: Processes messages
*
* MESSAGES:
*
* WM_COMMAND - application menu (About dialog box)
* WM_DESTROY - destroy window
*
* COMMENTS:
*
* To process the IDM_ABOUT message, call MakeProcInstance() to get the
* current instance address of the About() function. Then call Dialog
* box which will create the box according to the information in your
* aniedit.rc file and turn control over to the About() function. When
* it returns, free the intance address.
*
* History:
* 21-Apr-1993 JonPa Created it
*
\****************************************************************************/
BOOL APIENTRY MainWndProc(
HWND hWnd, /* window handle */
UINT message, /* type of message */
UINT wParam, /* additional information */
LONG lParam) /* additional information */
{
static HWND hwndChildApp = NULL;
static HBRUSH hbrBtnBar;
static HFONT hfontButton;
switch (message) {
case WM_INITDIALOG:
ghwndMain = hWnd;
gcrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
ghbrHighlight = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
ghbrWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
hbrBtnBar = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
hfontButton = CreateFont (GetHeightFromPoints(8), 0, 0, 0, 400,
0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS,
TEXT("AniEdit Button"));
SendDlgItemMessage (hWnd, DLG_MAIN_BTNNEW, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_BTNOPEN, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_BTNSAVE, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_BTNCUT, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_BTNCOPY, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_BTNPASTE, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_DELFRAME, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_ADDFRAME, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_EDITFRAME, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_PLAY, WM_SETFONT, (WPARAM)hfontButton, 0L);
SendDlgItemMessage (hWnd, DLG_MAIN_STOP, WM_SETFONT, (WPARAM)hfontButton, 0L);
#ifndef DBCS
// ANIBTN.FNT file has been changed. This font doesn't include
// capital letters. So we shouldn't set the font to this control.
SendDlgItemMessage (hWnd, DLG_MAIN_FRAMETXT, WM_SETFONT, (WPARAM)hfontButton, 0L);
#endif
GetWindowText(hWnd, gszWindowTitle, COUNTOF(gszWindowTitle));
/* cache scroll bar window handle */
ghwndRateScroll = GetDlgItem(hWnd, DLG_MAIN_RATESPIN);
/* limit title and author string lengths */
SendDlgItemMessage(hWnd, DLG_MAIN_TITLE, EM_LIMITTEXT,
COUNTOF(ganiAcon.azTitle), 0);
SendDlgItemMessage(hWnd, DLG_MAIN_AUTHOR, EM_LIMITTEXT,
COUNTOF(ganiAcon.azCreator), 0);
NewAniCursor(hWnd);
if (lParam != (LPARAM)NULL) {
HANDLE hf;
LPTSTR pszFileName = (LPTSTR)lParam;
hf = CreateFile(pszFileName, GENERIC_READ,
0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hf == INVALID_HANDLE_VALUE) {
// User may have left the file type off, add it on, and try
// again.
//
// HACK ALERT! -- This code assumes that pszFileName points
// to a buffer that is MAX_PATH in length.
//
int cchName;
cchName = lstrlen( pszFileName );
if (cchName + 4 < MAX_PATH) {
lstrcat( pszFileName, TEXT(".Ani") );
hf = CreateFile(pszFileName, GENERIC_READ,
0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hf == INVALID_HANDLE_VALUE) {
FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP,
TRUE, MSG_CANTOPENFILE, pszFileName );
return (TRUE);
}
}
}
LoadAniFile(hWnd, hf, pszFileName, pszFileName);
}
return (TRUE);
case WM_COMMAND: /* message: command from application menu */
return DoCommand( hWnd, wParam, lParam );
case AIM_SETCHILDAPP:
/*
* A child app has just been started. Remeber its hwnd and defer
* all activation to it.
*/
DPRINT(("MT:Child HWND = 0x%lx\n", lParam));
hwndChildApp = (HWND)lParam;
if (hwndChildApp == NULL)
EnableWindow(hWnd, FALSE);
break;
case AIM_PROCESSTERM:
/*
* The copy of ImagEdit that we spanwed off has just ended.
* Time to read in the cursor file and put it back into the list.
*/
/* "enable" our window */
DPRINT(("MT:got AIM_PROCESSTERM\n"));
hwndChildApp = NULL;
EnableWindow(hWnd, TRUE);
SetForegroundWindow(hWnd);
/* call CreateFrameFromCursorFile to reload the modified cursor */
if(CreateFrameFromCursorFile(hWnd, gszTempFile, gfEditFrame))
DeleteFile(gszTempFile);
break;
case WM_ACTIVATE:
/*
* Convert WM_ACTIVATE to WM_NCACTIVATE
*/
switch (LOWORD(wParam)) {
case WA_CLICKACTIVE:
/*
* Simulate disabled window's beep
*/
if (IsWindow( hwndChildApp ))
MessageBeep(MB_OK);
wParam = TRUE;
break;
case WA_ACTIVE:
wParam = TRUE;
break;
default:
wParam = FALSE;
break;
}
FALLTHRU(WM_NCACTIVATE);
case WM_NCACTIVATE:
case WM_ACTIVATEAPP:
DPRINT(("MT:got Activate (%04x) %c %08x\n", message, wParam ? 'T' : 'F', lParam));
if (wParam == TRUE && IsWindow( hwndChildApp )) {
/*
* We have a 'modal' child app upp, defer the activation to it.
*/
DPRINT(("MT:Defering Now\n"));
return SetForegroundWindow(hwndChildApp);
}
/*
* Let DefWndProc process this message
*/
return FALSE;
case WM_MEASUREITEM:
((MEASUREITEMSTRUCT *)lParam)->itemHeight = gcyCursor + 2;
break;
case WM_DRAWITEM:
DrawCursorListItem((DRAWITEMSTRUCT *)lParam);
break;
case WM_DELETEITEM: {
PSTEP ps;
if (wParam != DLG_MAIN_FRAMELIST)
return FALSE;
ps = (PSTEP)((LPDELETEITEMSTRUCT)lParam)->itemData;
if (IsValidPS(ps)) {
DestroyStep(ps);
}
break;
}
case WM_VSCROLL:
if( (HWND)lParam == ghwndRateScroll ) {
LONG iDelta;
switch( LOWORD(wParam) ) {
case SB_LINEUP:
case SB_PAGEUP:
iDelta = 1;
break;
case SB_LINEDOWN:
case SB_PAGEDOWN:
iDelta = -1;
break;
default:
iDelta = 0;
}
if (iDelta != 0) {
BOOL fOK;
JIF jifRate = GetDlgItemInt(hWnd, DLG_MAIN_RATE, &fOK, FALSE);
if( fOK ) {
if ((jifRate += iDelta) != 0) {
int *piSel, cSel;
SetDlgItemInt(hWnd, DLG_MAIN_RATE, jifRate, FALSE);
cSel = GetSelStepCount(hWnd);
if (cSel > 0 && (piSel = AllocMem(cSel * sizeof(int))) !=
NULL) {
int i;
ganiAcon.fDirty = TRUE;
GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, piSel, cSel,
&cSel);
for( i = 0; i < cSel; i++ ) {
PSTEP ps = GetStep(hWnd, piSel[i]);
if (IsValidPS(ps)) {
ps->jif = jifRate;
}
}
InvalidateRect(GetDlgItem(hWnd, DLG_MAIN_FRAMELIST),
NULL, TRUE);
FreeMem(piSel);
}
}
} else {
int *piSel, cSel, i;
JIF jifMin, jifTmp;
cSel = GetSelStepCount(hWnd);
if (cSel > 0 && (piSel = AllocMem(cSel * sizeof(int))) !=
NULL) {
ganiAcon.fDirty = TRUE;
GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, piSel, cSel,
&cSel);
jifMin = MAXLONG;
for( i = 0; i < cSel; i++ ) {
PSTEP ps = GetStep(hWnd, piSel[i]);
if (IsValidPS(ps)) {
jifMin = min(jifMin, ps->jif);
}
}
for( i = 0; i < cSel; i++ ) {
PSTEP ps = GetStep(hWnd, piSel[i]);
if (IsValidPS(ps)) {
jifTmp = ps->jif;
if (iDelta == 1) {
ps->jif += (ps->jif / jifMin);
} else {
ps->jif -= (ps->jif / jifMin);
}
/* check for over/under-flow */
if (ps->jif == 0) {
ps->jif = jifTmp;
}
}
}
InvalidateRect(GetDlgItem(hWnd, DLG_MAIN_FRAMELIST),
NULL, TRUE);
FreeMem(piSel);
}
}
}
}
break;
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE) {
ExitCommand(hWnd);
} else {
return FALSE;
}
break;
case WM_SYSCOLORCHANGE:
DeleteObject(ghbrPrevBackgnd);
DeleteObject(ghbrWindow);
DeleteObject(ghbrHighlight);
DeleteObject(hbrBtnBar);
ghbrHighlight = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
gcrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
ghbrWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
ghbrPrevBackgnd = CreateSolidBrush(GetSysColor(
garadColor[giradColor].idSys));
hbrBtnBar = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
break;
case WM_ERASEBKGND:
if (IsIconic(hWnd)) {
RECT rc;
HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
GetClientRect(hWnd, &rc);
FillRect((HDC)wParam, &rc, hbr);
DeleteObject(hbr);
break;
} else {
RECT rc;
// Fix this to use a real tool bar
HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
GetClientRect(hWnd, &rc);
FillRect((HDC)wParam, &rc, hbr);
DeleteObject(hbr);
GetWindowRect(GetDlgItem(hWnd, DLG_MAIN_BTNBAR), &rc);
ScreenToClient(hWnd, (LPPOINT)&(rc.left));
ScreenToClient(hWnd, (LPPOINT)&(rc.right));
FillRect((HDC)wParam, &rc, hbrBtnBar);
}
break;
case WM_PAINT:
if (IsIconic(hWnd)) {
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps);
DrawIcon(hdc, 0, 0, ghIcon);
EndPaint(hWnd, &ps);
break;
} else
return FALSE;
case WM_DESTROY:
#ifdef DBCS
GlobalFree(gpszAniFilter);
GlobalFree(gpszCurFilter);
GlobalFree(gpszUnknownError);
GlobalFree(gpszUntitled);
GlobalFree(gpszImport);
#endif
DeleteObject(ghbrPrevBackgnd);
DeleteObject(ghbrWindow);
DeleteObject(ghbrHighlight);
DeleteObject(hbrBtnBar);
DeleteObject(hfontButton );
PostQuitMessage(0);
return FALSE;
#if 0
case WM_CHAR:
switch( (TCHAR)wParam ) {
case CTRL_X:
PostMessage(hWnd, WM_COMMAND, MENU_EDIT_CUT, 0L);
break;
case CTRL_C:
PostMessage(hWnd, WM_COMMAND, MENU_EDIT_COPY, 0L);
break;
case CTRL_V:
PostMessage(hWnd, WM_COMMAND, MENU_EDIT_PASTE, 0L);
break;
}
// fall through to DefDlgProc
#endif
default:
return FALSE;
}
return TRUE;
}
/***************************************************************************\
*
* DrawCursorListItem
*
*
* History:
* 22-Dec-1991 DarrinM Created in the Cursors cpa.
* 22-Apr-1993 JonPa copied into this app and tweeked it.
\***************************************************************************/
void DrawCursorListItem(
DRAWITEMSTRUCT *pdis)
{
COLORREF crPrev;
static LONG cxAvgChar = 0;
TEXTMETRIC tm;
PSTEP ps;
TCHAR szJif[CCH_JIF];
/*
* If item == -1 and we are getting the focus, then draw an empty
* focus rect.
*/
if (pdis->itemAction == ODA_FOCUS && pdis->itemID == (UINT)-1) {
FillRect(pdis->hDC, &pdis->rcItem, ghbrWindow);
if (pdis->itemState & ODS_FOCUS) {
RECT rc;
CopyRect( &rc, &pdis->rcItem );
InflateRect( &rc, -2, -2 );
DrawFocusRect(pdis->hDC, &rc);
}
return;
}
/* find the average char width for this listbox and cache it */
if (cxAvgChar == 0) {
if (GetTextMetrics( pdis->hDC, &tm)) {
cxAvgChar = tm.tmAveCharWidth;
}
}
if (!(ps = (PSTEP)(pdis->itemData)))
return;
SetBkMode(pdis->hDC, TRANSPARENT);
if (pdis->itemState & ODS_SELECTED) {
FillRect(pdis->hDC, &pdis->rcItem, ghbrHighlight);
crPrev = SetTextColor(pdis->hDC, gcrHighlightText);
} else {
FillRect(pdis->hDC, &pdis->rcItem, ghbrWindow);
}
/* Draw the frame */
DrawIcon(pdis->hDC, pdis->rcItem.left + 2, pdis->rcItem.top + 1,
ps->pfrmFrame->hcur);
pdis->rcItem.left += gcxCursor + 2 + ((cxAvgChar != 0) ? cxAvgChar : 8);
/* write the rate text */
wsprintf( szJif, "%d", (int)ps->jif );
DrawText(pdis->hDC, szJif, strlen(szJif), &pdis->rcItem,
DT_SINGLELINE | DT_LEFT | DT_VCENTER);
if (pdis->itemState & ODS_SELECTED) {
SetTextColor(pdis->hDC, crPrev);
}
if (pdis->itemState & ODS_FOCUS) {
RECT rc;
CopyRect( &rc, &pdis->rcItem );
InflateRect( &rc, -1, -2 );
OffsetRect( &rc, -1, 0 );
DrawFocusRect(pdis->hDC, &rc);
}
}
/***************************************************************************\
*
* FUNCTION: FmtMessageBox( HWND hwnd, DWORD dwTitleID, UINT fuStyle,
* BOOL fSound, DWORD dwTextID, ... );
*
* PURPOSE: Formats messages with FormatMessage and then displays them
* in a message box
*
*
*
*
* History:
* 22-Apr-1993 JonPa Created it.
\***************************************************************************/
int FmtMessageBox( HWND hwnd, DWORD dwTitleID, LPTSTR pszTitleStr,
UINT fuStyle, BOOL fSound, DWORD dwTextID, ... ) {
LPTSTR pszMsg;
LPTSTR pszTitle;
int idRet;
va_list marker;
va_start( marker, dwTextID );
if(!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK, hInst,
dwTextID, 0, (LPTSTR)&pszMsg, 1, &marker))
pszMsg = gpszUnknownError;
va_end( marker );
GetLastError();
pszTitle = NULL;
if (dwTitleID == (DWORD)-1 ||
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK |
FORMAT_MESSAGE_ARGUMENT_ARRAY,
hInst, dwTitleID, 0, (LPTSTR)&pszTitle, 1, (va_list *)(DWORD)&pszTitleStr)) {
}
GetLastError();
if (fSound) {
MessageBeep( fuStyle & (MB_ICONASTERISK | MB_ICONEXCLAMATION |
MB_ICONHAND | MB_ICONQUESTION | MB_OK) );
}
idRet = MessageBox(hwnd, pszMsg, pszTitle, fuStyle);
if (pszTitle != NULL)
LocalFree( pszTitle );
if (pszMsg != gpszUnknownError)
LocalFree( pszMsg );
return idRet;
}
/***************************************************************************\
*
* FUNCTION: FmtSprintf( DWORD id, ... );
*
* PURPOSE: sprintf but it gets the pattern string from the message rc.
*
* History:
* 03-May-1993 JonPa Created it.
\***************************************************************************/
LPTSTR FmtSprintf( DWORD id, ... ) {
LPTSTR pszMsg;
va_list marker;
va_start( marker, id );
if(!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK, hInst,
id, 0, (LPTSTR)&pszMsg, 1, &marker)) {
GetLastError();
pszMsg = gszDots;
}
va_end( marker );
return pszMsg;
}
/***************************************************************************\
*
* FUNCTION: PVOID AllocMem( DWORD cb );
*
* PURPOSE: allocates memory, checking for errors
*
* History:
* 22-Apr-1993 JonPa Wrote it.
\***************************************************************************/
PVOID AllocMem( DWORD cb ) {
PVOID pv = (PVOID)LocalAlloc(LPTR, cb);
if (pv == NULL) {
FmtMessageBox( ghwndMain, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP,
TRUE, MSG_OUTOFMEM );
}
return pv;
}
/***************************************************************************\
* PreviewWndProc
*
*
* History:
* 08-07-92 DarrinM Created in CURSORS.CPL.
* 24-Apr-1993 JonPa Copied here and tweeked.
\***************************************************************************/
LRESULT CALLBACK
PreviewWndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
HDC hdc;
RECT rc;
PAINTSTRUCT ps;
PPREVIEWDATA ppd;
static int cxBM, cyBM;
static int cxCenter, cyCenter;
switch (msg) {
case WM_CREATE:
if (!(ppd = (PPREVIEWDATA)LocalAlloc(LPTR, sizeof(PREVIEWDATA))))
return -1;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)ppd);
/*
* Create a temp DC and bitmap to be used for buffering the
* preview rendering.
*/
cxCenter = gcxCursor;
cyCenter = gcyCursor;
cxBM = cxCenter * 2;
cyBM = cyCenter * 2;
hdc = GetDC(hwnd);
ppd->hdcMem = CreateCompatibleDC(hdc);
ppd->hbmMem = CreateCompatibleBitmap(hdc, cxBM, cyBM);
ppd->hbmOld = SelectObject(ppd->hdcMem, ppd->hbmMem);
ppd->iFrame = 0;
ppd->hcur = NULL;
ppd->xHot = ppd->yHot = 0;
ReleaseDC(hwnd, hdc);
break;
case WM_SIZE:
ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
SelectObject(ppd->hdcMem, ppd->hbmOld);
DeleteObject(ppd->hbmMem);
cxBM = LOWORD(lParam);
cyBM = HIWORD(lParam);
cxCenter = cxBM / 2;
cyCenter = cyBM / 2;
hdc = GetDC(hwnd);
ppd->hbmMem = CreateCompatibleBitmap(hdc, cxBM, cyBM);
ppd->hbmOld = SelectObject(ppd->hdcMem, ppd->hbmMem);
ReleaseDC(hwnd, hdc);
break;
case WM_DESTROY:
ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
SelectObject(ppd->hdcMem, ppd->hbmOld);
DeleteObject(ppd->hbmMem);
DeleteDC(ppd->hdcMem);
LocalFree(ppd);
break;
case PM_PAUSEANIMATION:
KillTimer(hwnd, ID_PREVIEWTIMER);
break;
case PM_UNPAUSEANIMATION:
NextFrame(hwnd, TRUE);
break;
case PM_NEWCURSOR:
wParam = 0;
FALLTHRU(PM_SETSTEP);
case PM_SETSTEP: {
BOOL fRun = KillTimer(hwnd, ID_PREVIEWTIMER);
ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
ppd->iFrame = wParam;
NextFrame(hwnd, fRun);
InvalidateRect(hwnd, NULL, FALSE);
break;
}
case WM_TIMER:
if (wParam != ID_PREVIEWTIMER)
break;
NextFrame(hwnd, TRUE);
break;
case WM_PAINT:
BeginPaint(hwnd, &ps);
ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
if (ppd->hcur != NULL)
{
rc.left = rc.top = 0;
rc.right = cxBM;
rc.bottom = cyBM;
FillRect(ppd->hdcMem, &rc, ghbrPrevBackgnd);
DrawIcon(ppd->hdcMem, cxCenter - ppd->xHot, cyCenter - ppd->yHot,
ppd->hcur);
BitBlt(ps.hdc, 0, 0, cxBM, cyBM, ppd->hdcMem, 0, 0, SRCCOPY);
}
else
{
FillRect(ps.hdc, &ps.rcPaint, ghbrPrevBackgnd);
}
EndPaint(hwnd, &ps);
break;
case WM_ERASEBKGND:
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
/*****************************************************************************\
* NextFrame
*
* Sets up for the next frame in the preview window.
*
* Arguments:
* HWND hwnd - Dialog window handle.
*
\*****************************************************************************/
VOID
NextFrame(
HWND hwnd, BOOL fRun
)
{
PPREVIEWDATA ppd;
HWND hwndLB;
DWORD cFrame;
PSTEP ps;
ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
//
// Be sure there is a cursor specified. If not, or it is
// not an animated cursor, we are done.
//
hwndLB = GetDlgItem(GetParent(hwnd), DLG_MAIN_FRAMELIST);
cFrame = SendMessage(hwndLB, LB_GETCOUNT, 0, 0);
if (cFrame == LB_ERR || cFrame == 0) {
ppd->hcur = NULL;
InvalidateRect(hwnd, NULL, FALSE);
return;
}
if (ppd->iFrame >= cFrame)
ppd->iFrame = 0;
/*
* Find how long this frame should be displayed (i.e. get jifRate)
*/
ps = (PSTEP)SendMessage(hwndLB, LB_GETITEMDATA, ppd->iFrame, 0);
if (IsValidPS(ps)) {
ppd->xHot = ps->pfrmFrame->xHotSpot;
ppd->yHot = ps->pfrmFrame->yHotSpot;
ppd->hcur = ps->pfrmFrame->hcur;
if (fRun)
SetTimer(hwnd, ID_PREVIEWTIMER, ps->jif * 16, NULL);
ppd->iFrame += 1;
} else {
ppd->hcur = NULL;
}
/*
* Redraw this frame of the cursor.
*/
InvalidateRect(hwnd, NULL, FALSE);
}
/*****************************************************************************\
* ReadRegistry
*
* Opens (creates if necessary) the registry key for preferences and then
* reads the last saved values.
*
* 03-Jul-1993 JonPa Copied from Spy, but changed greatly
*
\*****************************************************************************/
VOID ReadRegistry( VOID ) {
DWORD dw;
DWORD cbData;
HKEY hkey;
if (RegOpenKeyEx(HKEY_CURRENT_USER, gszAppKey, 0, KEY_QUERY_VALUE, &hkey)){
lstrcpy( gszCursorEditor, gpszImagEdit );
} else {
cbData = sizeof(gszCursorEditor);
if (RegQueryValueEx(hkey, gszKeyCurEditor, NULL, NULL,
gszCursorEditor, &cbData) != ERROR_SUCCESS) {
lstrcpy( gszCursorEditor, gpszImagEdit );
}
cbData = sizeof(dw);
if (RegQueryValueEx(hkey, gszKeyPrevColor, NULL, NULL, (LPBYTE)&dw,
&cbData) == ERROR_SUCCESS) {
giradColor = (int)dw;
}
RegCloseKey(hkey);
}
ghbrPrevBackgnd = CreateSolidBrush(GetSysColor(garadColor[giradColor].idSys));
}
/*****************************************************************************\
* WriteRegistry
*
* Writes out preference data to the registry when the app exits, then
* closes the registry key.
*
* 03-Jul-1993 JonPa Copied from Spy, but changed greatly
\*****************************************************************************/
VOID WriteRegistry( VOID ) {
HKEY hkey;
DWORD dw;
if (RegCreateKeyEx(HKEY_CURRENT_USER, gszAppKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dw))
return;
RegSetValueEx(hkey, gszKeyCurEditor, 0, REG_SZ, gszCursorEditor,
lstrlen(gszCursorEditor)+1);
dw = giradColor;
RegSetValueEx(hkey, gszKeyPrevColor, 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw));
RegCloseKey(hkey);
}
#ifdef DBCS
/*****************************************************************************\
* LoadResourceStr
*
* Load resource string.
*
\*****************************************************************************/
BOOL LoadResourceStr( VOID ) {
static TCHAR lpszTmp[MAX_PATH];
static TCHAR lpszBuf[MAX_PATH];
UINT wID;
INT nLen, nOffset;
/* Load Ani Filter */
for(wID = IDS_ANI_FILTER1, nOffset = 0; wID <= IDS_ANI_FILTER4; wID++) {
nLen = LoadString(hInst,wID,lpszTmp,sizeof(lpszTmp));
lstrcpy(&lpszBuf[nOffset],lpszTmp);
nOffset += nLen + 1;
}
nLen += nOffset + 1;
if((gpszAniFilter = (LPTSTR)GlobalAlloc(GMEM_FIXED,nLen)) == NULL)
return FALSE;
CopyMemory(gpszAniFilter,lpszBuf,nLen);
/* Load Cur Filter */
for(wID = IDS_CUR_FILTER1, nOffset = 0; wID <= IDS_CUR_FILTER6; wID++) {
nLen = LoadString(hInst,wID,lpszTmp,sizeof(lpszTmp));
lstrcpy(&lpszBuf[nOffset],lpszTmp);
nOffset += nLen + 1;
}
nLen += nOffset + 1;
if((gpszCurFilter = (LPTSTR)GlobalAlloc(GMEM_FIXED,nLen)) == NULL)
return FALSE;
CopyMemory(gpszCurFilter,lpszBuf,nLen);
/* Load Other strings */
nLen = LoadString(hInst,IDS_UNKNOWN_ERROR,lpszBuf,sizeof(lpszBuf));
if((gpszUnknownError = (LPTSTR)GlobalAlloc(
GMEM_FIXED,nLen+1)) == NULL)
return FALSE;
lstrcpy(gpszUnknownError,lpszBuf);
nLen = LoadString(hInst,IDS_UNTITLED,lpszBuf,sizeof(lpszBuf));
if((gpszUntitled = (LPTSTR)GlobalAlloc(
GMEM_FIXED,nLen+1)) == NULL)
return FALSE;
lstrcpy(gpszUntitled,lpszBuf);
nLen = LoadString(hInst,IDS_IMPORT,lpszBuf,sizeof(lpszBuf));
if((gpszImport = (LPTSTR)GlobalAlloc(
GMEM_FIXED,nLen+1)) == NULL)
return FALSE;
lstrcpy(gpszImport,lpszBuf);
return TRUE;
}
#endif