ANIEDIT.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:37k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /****************************************************************************
  2. *
  3. *     PROGRAM: AniEdit.c
  4. *
  5. *     PURPOSE: Animated Cursor Editor for Windows NT
  6. *
  7. *     Copyright 1993-1996 Microsoft Corp.
  8. *
  9. *
  10. * History:
  11. *   21-Apr-1993 JonPa   Wrote it.
  12. *
  13. ****************************************************************************/
  14. #include <windows.h>
  15. #include "anidefs.h"
  16. HANDLE hInst;
  17. HWND ghwndMain;
  18. HWND ghwndRateScroll = NULL;
  19. ANICUR ganiAcon;
  20. int gcyCursor, gcxCursor;
  21. HBRUSH  ghbrPrevBackgnd, ghbrWindow, ghbrHighlight;
  22. COLORREF gcrHighlightText;
  23. HICON   ghIcon;
  24. TCHAR   gszModPath[MAX_PATH];     /* name for above font module */
  25. TCHAR   gszWindowTitle[MAX_PATH] = TEXT("AniEdit");
  26. TCHAR   gszDots[] = TEXT("...");
  27. PFRAME  gpfrmFrames = NULL;
  28. PCLPBRDDAT gpbdClipBoard = NULL;
  29. TCHAR   gszCursorEditor[MAX_PATH];
  30. //HACCEL haccel;
  31. int giradColor = 0; /* Default to desktop color */
  32. RADIOCOLOR garadColor[] = {
  33.         {DLG_OPTIONS_RADIO_DESKCOL, COLOR_BACKGROUND},
  34.         {DLG_OPTIONS_RADIO_WINCOL,  COLOR_WINDOW},
  35.         {0, 0}
  36. };
  37. #if DLG_OPTIONS_RADIO_DESKCOL == 0 || DLG_OPTIONS_RADIO_WINCOL == 0
  38. #   error("Dialog IDs must not equal zero!")
  39. #endif
  40. /*
  41.  * Registry Strings
  42.  * (Since the registry is not localized, these don't have to be read in
  43.  *  from the strings RC)
  44.  */
  45. TCHAR gszAppKey[] = "Software\Microsoft\AniEdit";
  46. TCHAR gszKeyCurEditor[] = "Editor";
  47. TCHAR gszKeyPrevColor[] = "Preview Color";
  48. /****************************************************************************
  49. *
  50. *     FUNCTION: ParseCmdLine
  51. *
  52. *     PURPOSE: Returns a pointer to the first arg of the command line
  53. *
  54. * History:
  55. *   31-May-1995 JonPa   Created it
  56. *
  57. ****************************************************************************/
  58. TCHAR gszParseToken[MAX_PATH];
  59. LPTSTR ParseCmdLine( int iToken ) {
  60.     LPTSTR szFile;
  61.     LPTSTR szCmdLine;
  62.     BOOL fSkipBlank;
  63.     BOOL fInQuote;
  64.     fSkipBlank = TRUE;      // skip leading blanks
  65.     fInQuote = FALSE;
  66.     szFile = gszParseToken;
  67.     iToken++;
  68.     for(szCmdLine = GetCommandLine(); *szCmdLine != TEXT('') && iToken != 0;
  69.             szCmdLine++ ) {
  70.         switch (*szCmdLine) {
  71.         case TEXT('"'):
  72.             fInQuote = !fInQuote;
  73.             break;
  74.         case TEXT(' '):
  75.         case TEXT('t'):
  76.             if (fInQuote) {
  77.                 *szFile++ = *szCmdLine;
  78.             } else if (!fSkipBlank) {
  79.                 iToken--;
  80.                 *szFile++ = TEXT('');
  81.                 szFile = gszParseToken;
  82.                 fSkipBlank = TRUE;
  83.             }
  84.             break;
  85.         default:
  86.             *szFile++ = *szCmdLine;
  87.             fSkipBlank = FALSE;
  88.             break;
  89.         }
  90.     }
  91.     if (*szCmdLine == TEXT('') && !fSkipBlank ) {
  92.         iToken--;
  93.         *szFile++ = TEXT('');
  94.     }
  95.     if (iToken == 0 )
  96.         return gszParseToken;
  97.     else
  98.         return NULL;
  99. }
  100. /****************************************************************************
  101. *
  102. *     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  103. *
  104. *     PURPOSE: calls initialization function, processes message loop
  105. *
  106. *     COMMENTS:
  107. *
  108. *         Windows recognizes this function by name as the initial entry point
  109. *         for the program.  This function calls the application initialization
  110. *         routine, if no other instance of the program is running, and always
  111. *         calls the instance initialization routine.  It then executes a message
  112. *         retrieval and dispatch loop that is the top-level control structure
  113. *         for the remainder of execution.  The loop is terminated when a WM_QUIT
  114. *         message is received, at which time this function exits the application
  115. *         instance by returning the value passed by PostQuitMessage().
  116. *
  117. *         If this function must abort before entering the message loop, it
  118. *         returns the conventional value NULL.
  119. *
  120. * History:
  121. *   21-Apr-1993 JonPa   Created it
  122. *
  123. ****************************************************************************/
  124. int APIENTRY WinMain(
  125.     HINSTANCE hInstance,
  126.     HINSTANCE hPrevInstance,
  127.     LPSTR lpCmdLine,
  128.     int nCmdShow
  129.     )
  130. {
  131.     MSG msg;                                 /* message                      */
  132.     UNREFERENCED_PARAMETER( lpCmdLine );
  133.     if (!hPrevInstance)                  /* Other instances of app running? */
  134.         if (!InitApplication(hInstance)) /* Initialize shared things        */
  135.             return (FALSE);              /* Exits if unable to initialize   */
  136.     /* Perform initializations that apply to a specific instance */
  137.     if (!InitInstance(hInstance, nCmdShow))
  138.         return (FALSE);
  139.     ghIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ANI_ICON));
  140.     {   HACCEL hAccel;
  141.         HWND hwndDlg;
  142.         MSG msg;
  143.         hAccel = LoadAccelerators(hInstance, "AniEditMenu");
  144.         hwndDlg = CreateDialogParam( hInstance, MAKEINTRESOURCE(DLG_MAIN), GetDesktopWindow(),
  145.             MainWndProc, (LPARAM)ParseCmdLine(1) );
  146.         while (GetMessage(&msg, NULL, 0L, 0L))
  147.         {
  148.             if (!TranslateAccelerator(hwndDlg, hAccel, &msg))
  149.             {
  150.                 if (!IsDialogMessage(hwndDlg, &msg))
  151.                 {
  152.                     TranslateMessage(&msg);
  153.                     DispatchMessage(&msg);
  154.                 }
  155.             }
  156.         }
  157.     }
  158.     /* Write user profile */
  159.     WriteRegistry();
  160.     //BUGBUG - unregister preview class
  161.     if (gszModPath[0] != TEXT('')) {
  162.         RemoveFontResource(gszModPath);
  163.         PostMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
  164.     }
  165.     DeleteObject(ghbrPrevBackgnd);
  166.     /* Return the value from PostQuitMessage */
  167.     return (msg.wParam);
  168. }
  169. /****************************************************************************
  170. *
  171. *     FUNCTION: InitApplication(HANDLE)
  172. *
  173. *     PURPOSE: Initializes window data and registers window class
  174. *
  175. *     COMMENTS:
  176. *
  177. *         This function is called at initialization time only if no other
  178. *         instances of the application are running.  This function performs
  179. *         initialization tasks that can be done once for any number of running
  180. *         instances.
  181. *
  182. *         In this case, we initialize a window class by filling out a data
  183. *         structure of type WNDCLASS and calling the Windows RegisterClass()
  184. *         function.  Since all instances of this application use the same window
  185. *         class, we only need to do this when the first instance is initialized.
  186. *
  187. *
  188. ****************************************************************************/
  189. BOOL InitApplication(HANDLE hInstance)       /* current instance             */
  190. {
  191.     WNDCLASS cls;
  192.     /*
  193.      * Register a new window class to handle the cursor preview.
  194.      */
  195.     cls.style = 0;
  196.     cls.lpfnWndProc = PreviewWndProc;
  197.     cls.cbClsExtra = 0;
  198.     cls.cbWndExtra = 0;
  199.     cls.hInstance = hInstance;
  200.     cls.hIcon = NULL;
  201.     cls.hCursor = NULL;
  202.     cls.hbrBackground = NULL;
  203.     cls.lpszMenuName = NULL;
  204.     cls.lpszClassName = szPREVIEW;
  205.     RegisterClass(&cls);
  206.     AniAddFontModule(hInstance);
  207.     return TRUE;
  208. }
  209. void AniAddFontModule(HINSTANCE hInst) {
  210.     if (GetModuleFileName(hInst, gszModPath, MAX_PATH))
  211.         AddFontResource(gszModPath);
  212.     else
  213.         gszModPath[0] = TEXT('');
  214. }
  215. /****************************************************************************
  216. *
  217. *     FUNCTION:  InitInstance(HANDLE, int)
  218. *
  219. *     PURPOSE:  Saves instance handle and creates main window
  220. *
  221. *     COMMENTS:
  222. *
  223. *         This function is called at initialization time for every instance of
  224. *         this application.  This function performs initialization tasks that
  225. *         cannot be shared by multiple instances.
  226. *
  227. *         In this case, we save the instance handle in a static variable and
  228. *         create and display the main program window.
  229. *
  230. ****************************************************************************/
  231. BOOL InitInstance(
  232.     HANDLE          hInstance,
  233.     int             nCmdShow)
  234. {
  235.     /* Save the instance handle in static variable, which will be used in  */
  236.     /* many subsequence calls from this application to Windows.            */
  237.     hInst = hInstance;
  238.     gcyCursor = GetSystemMetrics(SM_CYCURSOR);
  239.     gcxCursor = GetSystemMetrics(SM_CXCURSOR);
  240. #ifdef DBCS
  241.     /* Load resource strings */
  242.     if (!LoadResourceStr())
  243.         return FALSE;
  244. #endif
  245.     /* Load user profile */
  246.     ReadRegistry();
  247. #if 0
  248.     /* Load the accel table */
  249.     if (!(haccel = LoadAccelerators(hInstance, "AniEditAccel")))
  250.         return FALSE;
  251. #endif
  252.     return (TRUE);               /* Returns the value from PostQuitMessage */
  253. }
  254. /* Copied from winfile:
  255.  */
  256. INT  APIENTRY GetHeightFromPoints( int pts)
  257. {
  258.     HDC hdc;
  259.     INT height;
  260.     hdc = GetDC (NULL);
  261.     height = MulDiv(-pts, GetDeviceCaps (hdc, LOGPIXELSY), 72);
  262.     ReleaseDC (NULL, hdc);
  263.     return height;
  264. }
  265. /****************************************************************************
  266. *
  267. *     FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  268. *
  269. *     PURPOSE:  Processes messages
  270. *
  271. *     MESSAGES:
  272. *
  273. *         WM_COMMAND    - application menu (About dialog box)
  274. *         WM_DESTROY    - destroy window
  275. *
  276. *     COMMENTS:
  277. *
  278. *         To process the IDM_ABOUT message, call MakeProcInstance() to get the
  279. *         current instance address of the About() function.  Then call Dialog
  280. *         box which will create the box according to the information in your
  281. *         aniedit.rc file and turn control over to the About() function.  When
  282. *         it returns, free the intance address.
  283. *
  284. * History:
  285. *   21-Apr-1993 JonPa   Created it
  286. *
  287. ****************************************************************************/
  288. BOOL APIENTRY MainWndProc(
  289.         HWND hWnd,                /* window handle                   */
  290.         UINT message,             /* type of message                 */
  291.         UINT wParam,              /* additional information          */
  292.         LONG lParam)              /* additional information          */
  293. {
  294.     static HWND     hwndChildApp = NULL;
  295.     static HBRUSH   hbrBtnBar;
  296.     static HFONT    hfontButton;
  297.     switch (message) {
  298.     case WM_INITDIALOG:
  299.         ghwndMain = hWnd;
  300.         gcrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  301.         ghbrHighlight = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  302.         ghbrWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  303.         hbrBtnBar = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  304.         hfontButton = CreateFont (GetHeightFromPoints(8), 0, 0, 0, 400,
  305.                                 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
  306.                                 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  307.                                 DEFAULT_PITCH | FF_SWISS,
  308.                                 TEXT("AniEdit Button"));
  309.         SendDlgItemMessage (hWnd, DLG_MAIN_BTNNEW, WM_SETFONT, (WPARAM)hfontButton, 0L);
  310.         SendDlgItemMessage (hWnd, DLG_MAIN_BTNOPEN, WM_SETFONT, (WPARAM)hfontButton, 0L);
  311.         SendDlgItemMessage (hWnd, DLG_MAIN_BTNSAVE, WM_SETFONT, (WPARAM)hfontButton, 0L);
  312.         SendDlgItemMessage (hWnd, DLG_MAIN_BTNCUT, WM_SETFONT, (WPARAM)hfontButton, 0L);
  313.         SendDlgItemMessage (hWnd, DLG_MAIN_BTNCOPY, WM_SETFONT, (WPARAM)hfontButton, 0L);
  314.         SendDlgItemMessage (hWnd, DLG_MAIN_BTNPASTE, WM_SETFONT, (WPARAM)hfontButton, 0L);
  315.         SendDlgItemMessage (hWnd, DLG_MAIN_DELFRAME, WM_SETFONT, (WPARAM)hfontButton, 0L);
  316.         SendDlgItemMessage (hWnd, DLG_MAIN_ADDFRAME, WM_SETFONT, (WPARAM)hfontButton, 0L);
  317.         SendDlgItemMessage (hWnd, DLG_MAIN_EDITFRAME, WM_SETFONT, (WPARAM)hfontButton, 0L);
  318.         SendDlgItemMessage (hWnd, DLG_MAIN_PLAY, WM_SETFONT, (WPARAM)hfontButton, 0L);
  319.         SendDlgItemMessage (hWnd, DLG_MAIN_STOP, WM_SETFONT, (WPARAM)hfontButton, 0L);
  320. #ifndef DBCS
  321.         // ANIBTN.FNT file has been changed. This font doesn't include
  322.         // capital letters. So we shouldn't set the font to this control.
  323.         SendDlgItemMessage (hWnd, DLG_MAIN_FRAMETXT, WM_SETFONT, (WPARAM)hfontButton, 0L);
  324. #endif
  325.         GetWindowText(hWnd, gszWindowTitle, COUNTOF(gszWindowTitle));
  326.         /* cache scroll bar window handle */
  327.         ghwndRateScroll = GetDlgItem(hWnd, DLG_MAIN_RATESPIN);
  328.         /* limit title and author string lengths */
  329.         SendDlgItemMessage(hWnd, DLG_MAIN_TITLE, EM_LIMITTEXT,
  330.                 COUNTOF(ganiAcon.azTitle), 0);
  331.         SendDlgItemMessage(hWnd, DLG_MAIN_AUTHOR, EM_LIMITTEXT,
  332.                 COUNTOF(ganiAcon.azCreator), 0);
  333.         NewAniCursor(hWnd);
  334.         if (lParam != (LPARAM)NULL) {
  335.             HANDLE hf;
  336.             LPTSTR pszFileName = (LPTSTR)lParam;
  337.             hf = CreateFile(pszFileName, GENERIC_READ,
  338.                     0, NULL,
  339.                     OPEN_EXISTING,
  340.                     FILE_ATTRIBUTE_NORMAL,
  341.                     NULL);
  342.             if (hf == INVALID_HANDLE_VALUE) {
  343.                 // User may have left the file type off, add it on, and try
  344.                 // again.
  345.                 //
  346.                 // HACK ALERT!  -- This code assumes that pszFileName points
  347.                 // to a buffer that is MAX_PATH in length.
  348.                 //
  349.                 int cchName;
  350.                 cchName = lstrlen( pszFileName );
  351.                 if (cchName + 4 < MAX_PATH) {
  352.                     lstrcat( pszFileName, TEXT(".Ani") );
  353.                     hf = CreateFile(pszFileName, GENERIC_READ,
  354.                             0, NULL,
  355.                             OPEN_EXISTING,
  356.                             FILE_ATTRIBUTE_NORMAL,
  357.                             NULL);
  358.                     if (hf == INVALID_HANDLE_VALUE) {
  359.                         FmtMessageBox( hWnd, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP,
  360.                             TRUE, MSG_CANTOPENFILE, pszFileName );
  361.                         return (TRUE);
  362.                     }
  363.                 }
  364.             }
  365.             LoadAniFile(hWnd, hf, pszFileName, pszFileName);
  366.         }
  367.         return (TRUE);
  368.     case WM_COMMAND:           /* message: command from application menu */
  369.         return DoCommand( hWnd, wParam, lParam );
  370.     case AIM_SETCHILDAPP:
  371.         /*
  372.          * A child app has just been started.  Remeber its hwnd and defer
  373.          * all activation to it.
  374.          */
  375.         DPRINT(("MT:Child HWND = 0x%lxn", lParam));
  376.         hwndChildApp = (HWND)lParam;
  377.         if (hwndChildApp == NULL)
  378.             EnableWindow(hWnd, FALSE);
  379.         break;
  380.     case AIM_PROCESSTERM:
  381.         /*
  382.          * The copy of ImagEdit that we spanwed off has just ended.
  383.          * Time to read in the cursor file and put it back into the list.
  384.          */
  385.         /* "enable" our window */
  386.         DPRINT(("MT:got AIM_PROCESSTERMn"));
  387.         hwndChildApp = NULL;
  388.         EnableWindow(hWnd, TRUE);
  389.         SetForegroundWindow(hWnd);
  390.         /* call CreateFrameFromCursorFile to reload the modified cursor */
  391.         if(CreateFrameFromCursorFile(hWnd, gszTempFile,  gfEditFrame))
  392.             DeleteFile(gszTempFile);
  393.         break;
  394.     case WM_ACTIVATE:
  395.         /*
  396.          * Convert WM_ACTIVATE to WM_NCACTIVATE
  397.          */
  398.         switch (LOWORD(wParam)) {
  399.         case WA_CLICKACTIVE:
  400.             /*
  401.              * Simulate disabled window's beep
  402.              */
  403.             if (IsWindow( hwndChildApp ))
  404.                 MessageBeep(MB_OK);
  405.             wParam = TRUE;
  406.             break;
  407.         case WA_ACTIVE:
  408.             wParam = TRUE;
  409.             break;
  410.         default:
  411.             wParam = FALSE;
  412.             break;
  413.         }
  414.         FALLTHRU(WM_NCACTIVATE);
  415.     case WM_NCACTIVATE:
  416.     case WM_ACTIVATEAPP:
  417.         DPRINT(("MT:got Activate (%04x) %c %08xn", message, wParam ? 'T' : 'F', lParam));
  418.         if (wParam == TRUE && IsWindow( hwndChildApp )) {
  419.             /*
  420.              * We have a 'modal' child app upp, defer the activation to it.
  421.              */
  422.             DPRINT(("MT:Defering Nown"));
  423.             return SetForegroundWindow(hwndChildApp);
  424.         }
  425.         /*
  426.          * Let DefWndProc process this message
  427.          */
  428.         return FALSE;
  429.     case WM_MEASUREITEM:
  430.         ((MEASUREITEMSTRUCT *)lParam)->itemHeight = gcyCursor + 2;
  431.         break;
  432.     case WM_DRAWITEM:
  433.         DrawCursorListItem((DRAWITEMSTRUCT *)lParam);
  434.         break;
  435.     case WM_DELETEITEM: {
  436.         PSTEP ps;
  437.         if (wParam != DLG_MAIN_FRAMELIST)
  438.             return FALSE;
  439.         ps = (PSTEP)((LPDELETEITEMSTRUCT)lParam)->itemData;
  440.         if (IsValidPS(ps)) {
  441.             DestroyStep(ps);
  442.         }
  443.         break;
  444.     }
  445.     case WM_VSCROLL:
  446.         if( (HWND)lParam == ghwndRateScroll ) {
  447.             LONG iDelta;
  448.             switch( LOWORD(wParam) ) {
  449.             case SB_LINEUP:
  450.             case SB_PAGEUP:
  451.                 iDelta = 1;
  452.                 break;
  453.             case SB_LINEDOWN:
  454.             case SB_PAGEDOWN:
  455.                 iDelta = -1;
  456.                 break;
  457.             default:
  458.                 iDelta = 0;
  459.             }
  460.             if (iDelta != 0) {
  461.                 BOOL fOK;
  462.                 JIF jifRate = GetDlgItemInt(hWnd, DLG_MAIN_RATE, &fOK, FALSE);
  463.                 if( fOK ) {
  464.                     if ((jifRate += iDelta) != 0) {
  465.                         int *piSel, cSel;
  466.                         SetDlgItemInt(hWnd, DLG_MAIN_RATE, jifRate, FALSE);
  467.                         cSel = GetSelStepCount(hWnd);
  468.                         if (cSel > 0 && (piSel = AllocMem(cSel * sizeof(int))) !=
  469.                                 NULL) {
  470.                             int i;
  471.                             ganiAcon.fDirty = TRUE;
  472.                             GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, piSel, cSel,
  473.                                     &cSel);
  474.                             for( i = 0; i < cSel; i++ ) {
  475.                                 PSTEP ps = GetStep(hWnd, piSel[i]);
  476.                                 if (IsValidPS(ps)) {
  477.                                     ps->jif = jifRate;
  478.                                 }
  479.                             }
  480.                             InvalidateRect(GetDlgItem(hWnd, DLG_MAIN_FRAMELIST),
  481.                                     NULL, TRUE);
  482.                             FreeMem(piSel);
  483.                         }
  484.                     }
  485.                 } else {
  486.                     int *piSel, cSel, i;
  487.                     JIF jifMin, jifTmp;
  488.                     cSel = GetSelStepCount(hWnd);
  489.                     if (cSel > 0 && (piSel = AllocMem(cSel * sizeof(int))) !=
  490.                             NULL) {
  491.                         ganiAcon.fDirty = TRUE;
  492.                         GetCurrentSel(hWnd, DLG_MAIN_FRAMELIST, piSel, cSel,
  493.                                 &cSel);
  494.                         jifMin = MAXLONG;
  495.                         for( i = 0; i < cSel; i++ ) {
  496.                             PSTEP ps = GetStep(hWnd, piSel[i]);
  497.                             if (IsValidPS(ps)) {
  498.                                 jifMin = min(jifMin, ps->jif);
  499.                             }
  500.                         }
  501.                         for( i = 0; i < cSel; i++ ) {
  502.                             PSTEP ps = GetStep(hWnd, piSel[i]);
  503.                             if (IsValidPS(ps)) {
  504.                                 jifTmp = ps->jif;
  505.                                 if (iDelta == 1) {
  506.                                     ps->jif += (ps->jif / jifMin);
  507.                                 } else {
  508.                                     ps->jif -= (ps->jif / jifMin);
  509.                                 }
  510.                                 /* check for over/under-flow */
  511.                                 if (ps->jif == 0) {
  512.                                     ps->jif = jifTmp;
  513.                                 }
  514.                             }
  515.                         }
  516.                         InvalidateRect(GetDlgItem(hWnd, DLG_MAIN_FRAMELIST),
  517.                                 NULL, TRUE);
  518.                         FreeMem(piSel);
  519.                     }
  520.                 }
  521.             }
  522.         }
  523.         break;
  524.     case WM_SYSCOMMAND:
  525.         if (wParam == SC_CLOSE) {
  526.             ExitCommand(hWnd);
  527.         } else {
  528.             return FALSE;
  529.         }
  530.         break;
  531.     case WM_SYSCOLORCHANGE:
  532.         DeleteObject(ghbrPrevBackgnd);
  533.         DeleteObject(ghbrWindow);
  534.         DeleteObject(ghbrHighlight);
  535.         DeleteObject(hbrBtnBar);
  536.         ghbrHighlight = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  537.         gcrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  538.         ghbrWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  539.         ghbrPrevBackgnd = CreateSolidBrush(GetSysColor(
  540.                 garadColor[giradColor].idSys));
  541.         hbrBtnBar = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  542.         break;
  543.     case WM_ERASEBKGND:
  544.         if (IsIconic(hWnd)) {
  545.             RECT rc;
  546.             HBRUSH hbr =  CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
  547.             GetClientRect(hWnd, &rc);
  548.             FillRect((HDC)wParam, &rc, hbr);
  549.             DeleteObject(hbr);
  550.             break;
  551.         } else {
  552.             RECT rc;
  553.             // Fix this to use a real tool bar
  554.             HBRUSH hbr =  CreateSolidBrush(GetSysColor(COLOR_3DFACE));
  555.             GetClientRect(hWnd, &rc);
  556.             FillRect((HDC)wParam, &rc, hbr);
  557.             DeleteObject(hbr);
  558.             GetWindowRect(GetDlgItem(hWnd, DLG_MAIN_BTNBAR), &rc);
  559.             ScreenToClient(hWnd, (LPPOINT)&(rc.left));
  560.             ScreenToClient(hWnd, (LPPOINT)&(rc.right));
  561.             FillRect((HDC)wParam, &rc, hbrBtnBar);
  562.         }
  563.         break;
  564.     case WM_PAINT:
  565.         if (IsIconic(hWnd)) {
  566.             HDC hdc;
  567.             PAINTSTRUCT ps;
  568.             hdc = BeginPaint(hWnd, &ps);
  569.             DrawIcon(hdc, 0, 0, ghIcon);
  570.             EndPaint(hWnd, &ps);
  571.             break;
  572.         } else
  573.             return FALSE;
  574.     case WM_DESTROY:
  575. #ifdef DBCS
  576.         GlobalFree(gpszAniFilter);
  577.         GlobalFree(gpszCurFilter);
  578.         GlobalFree(gpszUnknownError);
  579.         GlobalFree(gpszUntitled);
  580.         GlobalFree(gpszImport);
  581. #endif
  582.         DeleteObject(ghbrPrevBackgnd);
  583.         DeleteObject(ghbrWindow);
  584.         DeleteObject(ghbrHighlight);
  585.         DeleteObject(hbrBtnBar);
  586.         DeleteObject(hfontButton );
  587.         PostQuitMessage(0);
  588.         return FALSE;
  589. #if 0
  590.     case WM_CHAR:
  591.         switch( (TCHAR)wParam ) {
  592.         case CTRL_X:
  593.             PostMessage(hWnd, WM_COMMAND, MENU_EDIT_CUT, 0L);
  594.             break;
  595.         case CTRL_C:
  596.             PostMessage(hWnd, WM_COMMAND, MENU_EDIT_COPY, 0L);
  597.             break;
  598.         case CTRL_V:
  599.             PostMessage(hWnd, WM_COMMAND, MENU_EDIT_PASTE, 0L);
  600.             break;
  601.         }
  602.         // fall through to DefDlgProc
  603. #endif
  604.     default:
  605.         return FALSE;
  606.     }
  607.     return TRUE;
  608. }
  609. /***************************************************************************
  610. *
  611. * DrawCursorListItem
  612. *
  613. *
  614. * History:
  615. * 22-Dec-1991 DarrinM       Created in the Cursors cpa.
  616. * 22-Apr-1993 JonPa         copied into this app and tweeked it.
  617. ***************************************************************************/
  618. void DrawCursorListItem(
  619.     DRAWITEMSTRUCT *pdis)
  620. {
  621.     COLORREF crPrev;
  622.     static LONG cxAvgChar = 0;
  623.     TEXTMETRIC tm;
  624.     PSTEP ps;
  625.     TCHAR szJif[CCH_JIF];
  626.     /*
  627.      * If item == -1 and we are getting the focus, then draw an empty
  628.      * focus rect.
  629.      */
  630.     if (pdis->itemAction == ODA_FOCUS && pdis->itemID == (UINT)-1) {
  631.         FillRect(pdis->hDC, &pdis->rcItem, ghbrWindow);
  632.         if (pdis->itemState & ODS_FOCUS) {
  633.             RECT rc;
  634.             CopyRect( &rc, &pdis->rcItem );
  635.             InflateRect( &rc, -2, -2 );
  636.             DrawFocusRect(pdis->hDC, &rc);
  637.         }
  638.         return;
  639.     }
  640.     /* find the average char width for this listbox and cache it */
  641.     if (cxAvgChar == 0) {
  642.         if (GetTextMetrics( pdis->hDC, &tm)) {
  643.             cxAvgChar = tm.tmAveCharWidth;
  644.         }
  645.     }
  646.     if (!(ps = (PSTEP)(pdis->itemData)))
  647.         return;
  648.     SetBkMode(pdis->hDC, TRANSPARENT);
  649.     if (pdis->itemState & ODS_SELECTED) {
  650.         FillRect(pdis->hDC, &pdis->rcItem, ghbrHighlight);
  651.         crPrev = SetTextColor(pdis->hDC, gcrHighlightText);
  652.     } else {
  653.         FillRect(pdis->hDC, &pdis->rcItem, ghbrWindow);
  654.     }
  655.     /* Draw the frame */
  656.     DrawIcon(pdis->hDC, pdis->rcItem.left + 2, pdis->rcItem.top + 1,
  657.             ps->pfrmFrame->hcur);
  658.     pdis->rcItem.left += gcxCursor + 2 + ((cxAvgChar != 0) ? cxAvgChar : 8);
  659.     /* write the rate text */
  660.     wsprintf( szJif, "%d", (int)ps->jif );
  661.     DrawText(pdis->hDC, szJif, strlen(szJif), &pdis->rcItem,
  662.             DT_SINGLELINE | DT_LEFT | DT_VCENTER);
  663.     if (pdis->itemState & ODS_SELECTED) {
  664.         SetTextColor(pdis->hDC, crPrev);
  665.     }
  666.     if (pdis->itemState & ODS_FOCUS) {
  667.         RECT rc;
  668.         CopyRect( &rc, &pdis->rcItem );
  669.         InflateRect( &rc, -1, -2 );
  670.         OffsetRect( &rc, -1, 0 );
  671.         DrawFocusRect(pdis->hDC, &rc);
  672.     }
  673. }
  674. /***************************************************************************
  675. *
  676. *     FUNCTION: FmtMessageBox( HWND hwnd, DWORD dwTitleID, UINT fuStyle,
  677. *                   BOOL fSound, DWORD dwTextID, ... );
  678. *
  679. *     PURPOSE:  Formats messages with FormatMessage and then displays them
  680. *               in a message box
  681. *
  682. *
  683. *
  684. *
  685. * History:
  686. * 22-Apr-1993 JonPa         Created it.
  687. ***************************************************************************/
  688. int FmtMessageBox( HWND hwnd, DWORD dwTitleID, LPTSTR pszTitleStr,
  689.     UINT fuStyle, BOOL fSound, DWORD dwTextID, ... ) {
  690.     LPTSTR pszMsg;
  691.     LPTSTR pszTitle;
  692.     int idRet;
  693.     va_list marker;
  694.     va_start( marker, dwTextID );
  695.     if(!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  696.             FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK, hInst,
  697.             dwTextID, 0, (LPTSTR)&pszMsg, 1, &marker))
  698.         pszMsg = gpszUnknownError;
  699.     va_end( marker );
  700.     GetLastError();
  701.     pszTitle = NULL;
  702.     if (dwTitleID == (DWORD)-1 ||
  703.             FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  704.                 FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK |
  705.                 FORMAT_MESSAGE_ARGUMENT_ARRAY,
  706.                 hInst, dwTitleID, 0, (LPTSTR)&pszTitle, 1, (va_list *)(DWORD)&pszTitleStr)) {
  707.     }
  708.     GetLastError();
  709.     if (fSound) {
  710.         MessageBeep( fuStyle & (MB_ICONASTERISK | MB_ICONEXCLAMATION |
  711.                 MB_ICONHAND | MB_ICONQUESTION | MB_OK) );
  712.     }
  713.     idRet = MessageBox(hwnd, pszMsg, pszTitle, fuStyle);
  714.     if (pszTitle != NULL)
  715.         LocalFree( pszTitle );
  716.     if (pszMsg != gpszUnknownError)
  717.         LocalFree( pszMsg );
  718.     return idRet;
  719. }
  720. /***************************************************************************
  721. *
  722. *     FUNCTION: FmtSprintf( DWORD id, ... );
  723. *
  724. *     PURPOSE:  sprintf but it gets the pattern string from the message rc.
  725. *
  726. * History:
  727. * 03-May-1993 JonPa         Created it.
  728. ***************************************************************************/
  729. LPTSTR FmtSprintf( DWORD id, ... ) {
  730.     LPTSTR pszMsg;
  731.     va_list marker;
  732.     va_start( marker, id );
  733.     if(!FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  734.             FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK, hInst,
  735.             id, 0, (LPTSTR)&pszMsg, 1, &marker)) {
  736.         GetLastError();
  737.         pszMsg = gszDots;
  738.     }
  739.     va_end( marker );
  740.     return pszMsg;
  741. }
  742. /***************************************************************************
  743. *
  744. *     FUNCTION: PVOID AllocMem( DWORD cb );
  745. *
  746. *     PURPOSE:  allocates memory, checking for errors
  747. *
  748. * History:
  749. *   22-Apr-1993 JonPa   Wrote it.
  750. ***************************************************************************/
  751. PVOID AllocMem( DWORD cb ) {
  752.     PVOID pv = (PVOID)LocalAlloc(LPTR, cb);
  753.     if (pv == NULL) {
  754.         FmtMessageBox( ghwndMain, TITL_ERROR, NULL, MB_OK | MB_ICONSTOP,
  755.                 TRUE, MSG_OUTOFMEM );
  756.     }
  757.     return pv;
  758. }
  759. /***************************************************************************
  760. * PreviewWndProc
  761. *
  762. *
  763. * History:
  764. * 08-07-92 DarrinM      Created in CURSORS.CPL.
  765. * 24-Apr-1993 JonPa     Copied here and tweeked.
  766. ***************************************************************************/
  767. LRESULT CALLBACK
  768. PreviewWndProc(
  769.     HWND hwnd,
  770.     UINT msg,
  771.     WPARAM wParam,
  772.     LPARAM lParam
  773.     )
  774. {
  775.     HDC hdc;
  776.     RECT rc;
  777.     PAINTSTRUCT ps;
  778.     PPREVIEWDATA ppd;
  779.     static int cxBM, cyBM;
  780.     static int cxCenter, cyCenter;
  781.     switch (msg) {
  782.     case WM_CREATE:
  783.         if (!(ppd = (PPREVIEWDATA)LocalAlloc(LPTR, sizeof(PREVIEWDATA))))
  784.             return -1;
  785.         SetWindowLong(hwnd, GWL_USERDATA, (LONG)ppd);
  786.         /*
  787.          * Create a temp DC and bitmap to be used for buffering the
  788.          * preview rendering.
  789.          */
  790.         cxCenter = gcxCursor;
  791.         cyCenter = gcyCursor;
  792.         cxBM = cxCenter * 2;
  793.         cyBM = cyCenter * 2;
  794.         hdc = GetDC(hwnd);
  795.         ppd->hdcMem = CreateCompatibleDC(hdc);
  796.         ppd->hbmMem = CreateCompatibleBitmap(hdc, cxBM, cyBM);
  797.         ppd->hbmOld = SelectObject(ppd->hdcMem, ppd->hbmMem);
  798.         ppd->iFrame = 0;
  799.         ppd->hcur = NULL;
  800.         ppd->xHot = ppd->yHot = 0;
  801.         ReleaseDC(hwnd, hdc);
  802.         break;
  803.     case WM_SIZE:
  804.         ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
  805.         SelectObject(ppd->hdcMem, ppd->hbmOld);
  806.         DeleteObject(ppd->hbmMem);
  807.         cxBM = LOWORD(lParam);
  808.         cyBM = HIWORD(lParam);
  809.         cxCenter = cxBM / 2;
  810.         cyCenter = cyBM / 2;
  811.         hdc = GetDC(hwnd);
  812.         ppd->hbmMem = CreateCompatibleBitmap(hdc, cxBM, cyBM);
  813.         ppd->hbmOld = SelectObject(ppd->hdcMem, ppd->hbmMem);
  814.         ReleaseDC(hwnd, hdc);
  815.         break;
  816.     case WM_DESTROY:
  817.         ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
  818.         SelectObject(ppd->hdcMem, ppd->hbmOld);
  819.         DeleteObject(ppd->hbmMem);
  820.         DeleteDC(ppd->hdcMem);
  821.         LocalFree(ppd);
  822.         break;
  823.     case PM_PAUSEANIMATION:
  824.         KillTimer(hwnd, ID_PREVIEWTIMER);
  825.         break;
  826.     case PM_UNPAUSEANIMATION:
  827.         NextFrame(hwnd, TRUE);
  828.         break;
  829.     case PM_NEWCURSOR:
  830.         wParam = 0;
  831.         FALLTHRU(PM_SETSTEP);
  832.     case PM_SETSTEP: {
  833.         BOOL fRun = KillTimer(hwnd, ID_PREVIEWTIMER);
  834.         ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
  835.         ppd->iFrame = wParam;
  836.         NextFrame(hwnd, fRun);
  837.         InvalidateRect(hwnd, NULL, FALSE);
  838.         break;
  839.     }
  840.     case WM_TIMER:
  841.         if (wParam != ID_PREVIEWTIMER)
  842.             break;
  843.         NextFrame(hwnd, TRUE);
  844.         break;
  845.     case WM_PAINT:
  846.         BeginPaint(hwnd, &ps);
  847.         ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
  848.         if (ppd->hcur != NULL)
  849.         {
  850.             rc.left = rc.top = 0;
  851.             rc.right = cxBM;
  852.             rc.bottom = cyBM;
  853.             FillRect(ppd->hdcMem, &rc, ghbrPrevBackgnd);
  854.             DrawIcon(ppd->hdcMem, cxCenter - ppd->xHot, cyCenter - ppd->yHot,
  855.                     ppd->hcur);
  856.             BitBlt(ps.hdc, 0, 0, cxBM, cyBM, ppd->hdcMem, 0, 0, SRCCOPY);
  857.         }
  858.         else
  859.         {
  860.             FillRect(ps.hdc, &ps.rcPaint, ghbrPrevBackgnd);
  861.         }
  862.         EndPaint(hwnd, &ps);
  863.         break;
  864.     case WM_ERASEBKGND:
  865.         break;
  866.     default:
  867.         return DefWindowProc(hwnd, msg, wParam, lParam);
  868.     }
  869.     return 0;
  870. }
  871. /*****************************************************************************
  872. * NextFrame
  873. *
  874. * Sets up for the next frame in the preview window.
  875. *
  876. * Arguments:
  877. *   HWND hwnd - Dialog window handle.
  878. *
  879. *****************************************************************************/
  880. VOID
  881. NextFrame(
  882.     HWND hwnd, BOOL fRun
  883.     )
  884. {
  885.     PPREVIEWDATA ppd;
  886.     HWND hwndLB;
  887.     DWORD cFrame;
  888.     PSTEP ps;
  889.     ppd = (PPREVIEWDATA)GetWindowLong(hwnd, GWL_USERDATA);
  890.     //
  891.     // Be sure there is a cursor specified.  If not, or it is
  892.     // not an animated cursor, we are done.
  893.     //
  894.     hwndLB = GetDlgItem(GetParent(hwnd), DLG_MAIN_FRAMELIST);
  895.     cFrame = SendMessage(hwndLB, LB_GETCOUNT, 0, 0);
  896.     if (cFrame == LB_ERR || cFrame == 0) {
  897.         ppd->hcur = NULL;
  898.         InvalidateRect(hwnd, NULL, FALSE);
  899.         return;
  900.     }
  901.     if (ppd->iFrame >= cFrame)
  902.         ppd->iFrame = 0;
  903.     /*
  904.      * Find how long this frame should be displayed (i.e. get jifRate)
  905.      */
  906.     ps = (PSTEP)SendMessage(hwndLB, LB_GETITEMDATA, ppd->iFrame, 0);
  907.     if (IsValidPS(ps)) {
  908.         ppd->xHot = ps->pfrmFrame->xHotSpot;
  909.         ppd->yHot = ps->pfrmFrame->yHotSpot;
  910.         ppd->hcur = ps->pfrmFrame->hcur;
  911.         if (fRun)
  912.             SetTimer(hwnd, ID_PREVIEWTIMER, ps->jif * 16, NULL);
  913.         ppd->iFrame += 1;
  914.     } else {
  915.         ppd->hcur = NULL;
  916.     }
  917.     /*
  918.      * Redraw this frame of the cursor.
  919.      */
  920.     InvalidateRect(hwnd, NULL, FALSE);
  921. }
  922. /*****************************************************************************
  923. * ReadRegistry
  924. *
  925. * Opens (creates if necessary) the registry key for preferences and then
  926. * reads the last saved values.
  927. *
  928. *   03-Jul-1993 JonPa   Copied from Spy, but changed greatly
  929. *
  930. *****************************************************************************/
  931. VOID ReadRegistry( VOID ) {
  932.     DWORD dw;
  933.     DWORD cbData;
  934.     HKEY hkey;
  935.     if (RegOpenKeyEx(HKEY_CURRENT_USER, gszAppKey, 0, KEY_QUERY_VALUE, &hkey)){
  936.         lstrcpy( gszCursorEditor, gpszImagEdit );
  937.     } else {
  938.         cbData = sizeof(gszCursorEditor);
  939.         if (RegQueryValueEx(hkey, gszKeyCurEditor, NULL, NULL,
  940.             gszCursorEditor, &cbData) != ERROR_SUCCESS) {
  941.             lstrcpy( gszCursorEditor, gpszImagEdit );
  942.         }
  943.         cbData = sizeof(dw);
  944.         if (RegQueryValueEx(hkey, gszKeyPrevColor, NULL, NULL, (LPBYTE)&dw,
  945.                 &cbData) == ERROR_SUCCESS) {
  946.             giradColor = (int)dw;
  947.         }
  948.         RegCloseKey(hkey);
  949.     }
  950.     ghbrPrevBackgnd = CreateSolidBrush(GetSysColor(garadColor[giradColor].idSys));
  951. }
  952. /*****************************************************************************
  953. * WriteRegistry
  954. *
  955. * Writes out preference data to the registry when the app exits, then
  956. * closes the registry key.
  957. *
  958. *   03-Jul-1993 JonPa   Copied from Spy, but changed greatly
  959. *****************************************************************************/
  960. VOID WriteRegistry( VOID ) {
  961.     HKEY hkey;
  962.     DWORD dw;
  963.     if (RegCreateKeyEx(HKEY_CURRENT_USER, gszAppKey, 0, NULL,
  964.                 REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dw))
  965.         return;
  966.     RegSetValueEx(hkey, gszKeyCurEditor, 0, REG_SZ, gszCursorEditor,
  967.             lstrlen(gszCursorEditor)+1);
  968.     dw = giradColor;
  969.     RegSetValueEx(hkey, gszKeyPrevColor, 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw));
  970.     RegCloseKey(hkey);
  971. }
  972. #ifdef DBCS
  973. /*****************************************************************************
  974. * LoadResourceStr
  975. *
  976. * Load resource string.
  977. *
  978. *****************************************************************************/
  979. BOOL LoadResourceStr( VOID ) {
  980.     static TCHAR lpszTmp[MAX_PATH];
  981.     static TCHAR lpszBuf[MAX_PATH];
  982.     UINT  wID;
  983.     INT   nLen, nOffset;
  984.     /* Load Ani Filter */
  985.     for(wID = IDS_ANI_FILTER1, nOffset = 0; wID <= IDS_ANI_FILTER4; wID++) {
  986.         nLen = LoadString(hInst,wID,lpszTmp,sizeof(lpszTmp));
  987.         lstrcpy(&lpszBuf[nOffset],lpszTmp);
  988.         nOffset += nLen + 1;
  989.     }
  990.     nLen += nOffset + 1;
  991.     if((gpszAniFilter = (LPTSTR)GlobalAlloc(GMEM_FIXED,nLen)) == NULL)
  992.         return FALSE;
  993.     CopyMemory(gpszAniFilter,lpszBuf,nLen);
  994.     /* Load Cur Filter */
  995.     for(wID = IDS_CUR_FILTER1, nOffset = 0; wID <= IDS_CUR_FILTER6; wID++) {
  996.         nLen = LoadString(hInst,wID,lpszTmp,sizeof(lpszTmp));
  997.         lstrcpy(&lpszBuf[nOffset],lpszTmp);
  998.         nOffset += nLen + 1;
  999.     }
  1000.     nLen += nOffset + 1;
  1001.     if((gpszCurFilter = (LPTSTR)GlobalAlloc(GMEM_FIXED,nLen)) == NULL)
  1002.         return FALSE;
  1003.     CopyMemory(gpszCurFilter,lpszBuf,nLen);
  1004.     /* Load Other strings */
  1005.     nLen = LoadString(hInst,IDS_UNKNOWN_ERROR,lpszBuf,sizeof(lpszBuf));
  1006.     if((gpszUnknownError = (LPTSTR)GlobalAlloc(
  1007.                         GMEM_FIXED,nLen+1)) == NULL)
  1008.         return FALSE;
  1009.     lstrcpy(gpszUnknownError,lpszBuf);
  1010.     nLen = LoadString(hInst,IDS_UNTITLED,lpszBuf,sizeof(lpszBuf));
  1011.     if((gpszUntitled = (LPTSTR)GlobalAlloc(
  1012.                         GMEM_FIXED,nLen+1)) == NULL)
  1013.         return FALSE;
  1014.     lstrcpy(gpszUntitled,lpszBuf);
  1015.     nLen = LoadString(hInst,IDS_IMPORT,lpszBuf,sizeof(lpszBuf));
  1016.     if((gpszImport = (LPTSTR)GlobalAlloc(
  1017.                         GMEM_FIXED,nLen+1)) == NULL)
  1018.         return FALSE;
  1019.     lstrcpy(gpszImport,lpszBuf);
  1020.     return TRUE;
  1021. }
  1022. #endif