/****************************************************************************\ * * PROGRAM: AniEdit.c * * PURPOSE: Animated Cursor Editor for Windows NT * * Copyright 1993-1996 Microsoft Corp. * * * History: * 21-Apr-1993 JonPa Wrote it. * \****************************************************************************/ #include #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