home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / windows / c / itool3 / source / img_demo.c next >
Encoding:
C/C++ Source or Header  |  1993-12-20  |  37.0 KB  |  918 lines

  1. /********************************************************/
  2. /* Compile whith large memory model on Borland C or C++ */
  3. /* compiler and link with lsdemo.def and lsdemo.res     */
  4. /********************************************************/
  5.  
  6. #define EXTERN exter
  7. /* IMG_DEMO by Davor, AiM 1993 */
  8.  
  9. #include <windows.h>
  10. #include <commdlg.h>
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include <io.h>
  14.  
  15. #include "SYSPIC.H"
  16. #include "IMAGE_LS.H"
  17. #include "IMAGE_EF.H"
  18.  
  19. #include "IMG_DEMO.H"
  20.  
  21. #define MAX_NUM_PIC                        20
  22. /* Maximum number of opened windows is limited only with your system
  23.    resources and free RAM */
  24.  
  25. PICTURE         DemoPic[MAX_NUM_PIC];
  26. BOOL            fRemap=TRUE,fPaintEnd=TRUE;
  27. LPFRAME AniFrames[MAX_NUM_PIC];
  28. /* array AniFrames is used for loading FLI/FLC animation frames */
  29. short       nPicNum=0,      // Number of opened pictures
  30.         nActivePic=-1, // Number of active picture
  31.         nAniFrames=0, iStartFrame, iEndFrame; // Variables used for FLI/FLC load
  32.  
  33. /* Folowing variables and strings are used for FileSelect common dialog */
  34. OPENFILENAME ofn;
  35. char    szFileTitle[256], szFile[256];
  36. char    szFilterOpen[]="BMP (*.BMP)\0*.BMP\0GIF (*.GIF)\0*.GIF\0PCX (*.PCX)\0*.PCX\0Truevision TGA (*.TGA)\0*.TGA\0Color TIFF (*.TIF)\0*.TIF\0FLI (*.FLI)\0*.FLI\0FLC (*.FLC)\0*.FLC\0JPEG (*.JPG)\0*.JPG\0";
  37. char    szFilterSave[]="BMP (*.BMP)\0*.BMP\0GIF (*.GIF)\0*.GIF\0PCX (*.PCX)\0*.PCX\0Truevision TGA (*.TGA)\0*.TGA\0Color TIFF (*.TIF)\0*.TIF\0FLI (*.FLI)\0*.FLI\0FLC (*.FLC)\0*.FLC\0JPEG (*.JPG)\0*.JPG\0";
  38. char    *szFileExt[]={".XXX", ".BMP", ".GIF", ".PCX", ".TGA", ".TIF", ".FLI", ".FLC", ".JPG"};
  39. char    szDirName[256];
  40.  
  41.  
  42. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  43. {
  44.  /***********************************************************************/
  45.  /* HANDLE hInstance;       handle for this instance                    */
  46.  /* HANDLE hPrevInstance;   handle for possible previous instances      */
  47.  /* LPSTR  lpszCmdLine;     long pointer to exec command line           */
  48.  /* short    nCmdShow;        Show code for main window display         */
  49.  /***********************************************************************/
  50.  
  51.  MSG        msg;           /* MSG structure to store your messages      */
  52.  short        nRc;           /* return value from Register Classes        */
  53.  DLGPROC    lpfnDlgProc;
  54.  
  55.  strcpy(szAppName, "ITDEMO");
  56.  hInst = hInstance;
  57.  if(!hPrevInstance)
  58.    {
  59.     /* register window classes if first instance of application         */
  60.     if ((nRc = nCwRegisterClasses()) == -1)
  61.       {
  62.        /* registering one of the windows failed                         */       
  63.        LoadString(hInst, IDS_ERR_REGISTER_CLASS, szString, sizeof(szString));
  64.       MessageBox(NULL, szString, NULL, MB_ICONEXCLAMATION);
  65.        return nRc;    
  66.      }
  67.    }
  68.  
  69.  LoadString(hInst, IDS_MAINWND_TITLE, szString, sizeof(szString));
  70.  /* create application's Main window                                    */
  71.  hWndMain = CreateWindow(
  72.           szAppName,               /* Window class name           */
  73.           szString,             /* Window's title           */
  74.           WS_CAPTION      |        /* Title and Min/Max           */
  75.           WS_SYSMENU      |        /* Add system menu box         */
  76.           WS_MINIMIZEBOX  |        /* Add minimize box            */
  77.           WS_MAXIMIZEBOX  |        /* Add maximize box            */
  78.           WS_THICKFRAME   |        /* thick sizeable frame        */
  79.           WS_CLIPCHILDREN |         /* don't draw in child windows areas */
  80.           WS_OVERLAPPED,
  81.           CW_USEDEFAULT, 0,        /* Use default X, Y            */
  82.           CW_USEDEFAULT, 0,        /* Use default X, Y            */
  83.           NULL,                    /* Parent window's handle      */
  84.           NULL,                    /* Default to Class Menu       */
  85.           hInst,                   /* Instance of window          */
  86.           NULL);                   /* Create struct for WM_CREATE */
  87.  
  88.  
  89.  if(hWndMain == NULL)
  90.    {
  91.     LoadString(hInst, IDS_ERR_CREATE_WND, szString, sizeof(szString));
  92.     MessageBox(NULL, szString, NULL, MB_ICONEXCLAMATION);
  93.     return IDS_ERR_CREATE_WND;
  94.    }
  95.  
  96.  ShowWindow(hWndMain, nCmdShow);            /* display main window      */
  97.  
  98.  hAccel = LoadAccelerators(hInst, szAppName);   /* load accelerators */
  99.  hCursorNormal = LoadCursor(NULL, IDC_ARROW);   /* and two cursor types */
  100.  hCursorBusy = LoadCursor(NULL, IDC_WAIT);
  101.  hMenu=GetMenu(hWndMain);
  102.  memset(&ofn, 0, sizeof(OPENFILENAME));         /* File ofn structure for
  103.                                          common dialog...*/
  104.  ofn.lStructSize = sizeof(OPENFILENAME);
  105.  ofn.hwndOwner = hWndMain;
  106.  ofn.lpstrFile= szFile;
  107.  ofn.nMaxFile = sizeof(szFile);
  108.  ofn.lpstrFileTitle = szFileTitle;
  109.  ofn.nMaxFileTitle = sizeof(szFileTitle);
  110.  ofn.lpstrInitialDir = szDirName;
  111.  
  112.  CheckActiveWindow();                       /* Check menu visibility */
  113.  
  114.  while(GetMessage(&msg, NULL, 0, 0)) {       /* Until WM_QUIT message    */
  115.           if(TranslateAccelerator(hWndMain, hAccel, &msg))
  116.                continue;
  117.           TranslateMessage(&msg);
  118.           DispatchMessage(&msg);
  119.      }
  120.  
  121.  /* Do clean up before exiting from the application                     */
  122.  CwUnRegisterClasses();
  123.  return msg.wParam;
  124. } /*  End of WinMain                                                    */
  125.  
  126. /************************************************************************/
  127. /*                                                                      */
  128. /* Main Window Procedure                                                */
  129. /*                                                                      */
  130. /* This procedure provides service routines for the Windows events      */
  131. /* (messages) that Windows sends to the window, as well as the user     */
  132. /* initiated events (messages) that are generated when the user selects */
  133. /* the action bar and pulldown menu controls or the corresponding       */
  134. /* keyboard accelerators.                                               */
  135. /*                                                                      */
  136. /************************************************************************/
  137.  
  138. LONG FAR PASCAL WndProc(HWND hWnd, WORD Message, WORD wParam, LONG lParam)
  139. {
  140.  HDC            hDC;                /* handle for the display device       */
  141.  PAINTSTRUCT    ps;                /* holds PAINT information             */
  142.  FARPROC        lpfnDlgProc;
  143.  LPHBYTE        lpNewPic;
  144.  HANDLE         hNewPic;
  145.  RECT         Rect;
  146.  FRAME         Frame;
  147.  short          ret;
  148.  
  149.  switch (Message)
  150.    {
  151.     case WM_COMMAND:
  152.       /* The Windows messages for action bar and pulldown menu items */
  153.       /* are processed here.                                         */
  154.          hCursorNormal=SetCursor(hCursorBusy); // Show busy cursor
  155.          /* fill temporary frame structure with active frame data */
  156.         memcpy(&Frame, &DemoPic[nActivePic].Frame, sizeof(FRAME));
  157.          switch (wParam)
  158.          {
  159.             case IDM_CLOSE:
  160.                SendMessage(hActive, WM_SYSCOMMAND, IDM_CLOSE, 0L);
  161.               break;
  162.             case IDM_F_OPENPICTURE:
  163.                LoadSaveData(1);
  164.                CheckActiveWindow();
  165.                break;
  166.  
  167.                case IDM_F_SAVEPICTURE:
  168.                 LoadSaveData(3);
  169.             break; 
  170.  
  171.             case IDM_F_EXIT:
  172.           SendMessage(hWndMain,WM_CLOSE,0,0L);
  173.             break; 
  174.           /* Effect demo routines */
  175.           /* In every effect-function call second line consists of
  176.                 variable parameters */
  177.           case IDM_E_BLURE:
  178.             if(AllocFrame(Frame))
  179.                 ret=EffBlure(&(DemoPic[nActivePic].Frame), &Frame,
  180.                          10);        // Blure value = 10
  181.             goto EFFECT_EXIT;
  182.             case IDM_E_BRIGHTNESSU:
  183.             if(AllocFrame(Frame))
  184.                 ret=EffBrightness(&(DemoPic[nActivePic].Frame), &Frame,
  185.                     40);        // Brighten amount = 40
  186.                goto EFFECT_EXIT;
  187.             case IDM_E_BRIGHTNESSD:
  188.             if(AllocFrame(Frame))
  189.                 ret=EffBrightness(&(DemoPic[nActivePic].Frame), &Frame,
  190.                     -40);       // Darken amount = 40
  191.                goto EFFECT_EXIT;
  192.             case IDM_E_CONTRASTU:
  193.             if(AllocFrame(Frame))
  194.                 ret=EffContrast(&(DemoPic[nActivePic].Frame), &Frame,
  195.                     300);       // Contrast is modified to 300% of previous amount
  196.                goto EFFECT_EXIT;
  197.             case IDM_E_CONTRASTD:
  198.             if(AllocFrame(Frame))
  199.                 ret=EffContrast(&(DemoPic[nActivePic].Frame), &Frame,
  200.                     33);        // Contrast is modified to 33% of previous amount
  201.             goto EFFECT_EXIT;
  202.             case IDM_E_CROP:
  203.             if(AllocFrame(Frame))
  204.                 /* Cutoff the middle of the picture */
  205.                 ret=EffCrop(&(DemoPic[nActivePic].Frame), &Frame,
  206.                     DemoPic[nActivePic].Frame.iWidth/3,DemoPic[nActivePic].Frame.iHeight/3,DemoPic[nActivePic].Frame.iWidth*2/3,DemoPic[nActivePic].Frame.iHeight*2/3);
  207.             goto EFFECT_EXIT;
  208.           case IDM_E_EDGEDETECTION:
  209.             if(AllocFrame(Frame))
  210.                 /* Find the edges. Treshold is 30, and colours are white and black*/
  211.                 ret=EffEdgeDetection(&(DemoPic[nActivePic].Frame), &Frame,
  212.                     30, (DWORD)0x00FFFFFF /*white*/, (DWORD)0x00000000)/* black*/;
  213.             goto EFFECT_EXIT;
  214.             case IDM_E_FLIPH:
  215.             if(AllocFrame(Frame))
  216.                 ret=EffFlip(&(DemoPic[nActivePic].Frame), &Frame,
  217.                          0, 1);  // flip only horizontal
  218.                goto EFFECT_EXIT;
  219.             case IDM_E_FLIPV:
  220.             if(AllocFrame(Frame))
  221.                 ret=EffFlip(&(DemoPic[nActivePic].Frame), &Frame,
  222.                          1, 0);  // flip only vertical
  223.                goto EFFECT_EXIT;
  224.           /* four following calls move the picture for the half of its size */
  225.           case IDM_E_MOVEL:
  226.                /* left */
  227.             if(AllocFrame(Frame))
  228.                 ret=EffMove(&(DemoPic[nActivePic].Frame), &Frame,
  229.                     -(short)(DemoPic[nActivePic].Frame.iWidth/2), 0);
  230.                goto EFFECT_EXIT;
  231.             case IDM_E_MOVER:
  232.             /* right */
  233.             if(AllocFrame(Frame))
  234.                 ret=EffMove(&(DemoPic[nActivePic].Frame), &Frame,
  235.                     DemoPic[nActivePic].Frame.iWidth/2, 0);
  236.                goto EFFECT_EXIT;
  237.             case IDM_E_MOVEU:
  238.             /* up */
  239.             if(AllocFrame(Frame)) 
  240.                 ret=EffMove(&(DemoPic[nActivePic].Frame), &Frame,
  241.                     0, DemoPic[nActivePic].Frame.iHeight/2);
  242.                goto EFFECT_EXIT;
  243.             case IDM_E_MOVED:
  244.             /* down */
  245.             if(AllocFrame(Frame))
  246.                 ret=EffMove(&(DemoPic[nActivePic].Frame), &Frame,
  247.                     0, -(short)(DemoPic[nActivePic].Frame.iHeight/2));
  248.                goto EFFECT_EXIT;
  249.           case IDM_E_ROTATE45:
  250.                 /* rotate the picture for 45 degrees whith rotation center in the middle */
  251.             if(AllocFrame(Frame))
  252.                 ret=EffRotate(&(DemoPic[nActivePic].Frame), &Frame,
  253.                     DemoPic[nActivePic].Frame.iWidth/2, DemoPic[nActivePic].Frame.iHeight/2, 45);
  254.                goto EFFECT_EXIT;
  255.           case IDM_E_ROTATE90:
  256.             /* same, but the rotation angle is 90 degrees */
  257.             if(AllocFrame(Frame))
  258.                 ret=EffRotate(&(DemoPic[nActivePic].Frame), &Frame,
  259.                     DemoPic[nActivePic].Frame.iWidth/2, DemoPic[nActivePic].Frame.iHeight/2, 90);
  260.                goto EFFECT_EXIT;
  261.           case IDM_E_SCALE:
  262.                /* scale the window to fit the new size */
  263.             GetClientRect(hActive, &Rect);
  264.             Frame.iWidth=Rect.right-Rect.left;
  265.             Frame.iHeight=Rect.bottom-Rect.top;
  266.             if(AllocFrame(Frame))
  267.                 ret=EffScale(&(DemoPic[nActivePic].Frame), &Frame,
  268.                          TRUE);
  269.             goto EFFECT_EXIT;
  270.           case IDM_E_ZOOM:
  271.             /* zoom in the middle of the window */
  272.             if(AllocFrame(Frame))
  273.                 ret=EffZoom(&(DemoPic[nActivePic].Frame), &Frame,
  274.                     DemoPic[nActivePic].Frame.iWidth/3,DemoPic[nActivePic].Frame.iHeight/3,DemoPic[nActivePic].Frame.iWidth*2/3,DemoPic[nActivePic].Frame.iHeight*2/3);
  275.                goto EFFECT_EXIT;
  276.           case IDM_E_SHARPEN:
  277.                /* sharpen the picture (opposit of blure) */
  278.             if(AllocFrame(Frame))
  279.                 ret=EffSharpen(&(DemoPic[nActivePic].Frame), &Frame,
  280.                          300);
  281. EFFECT_EXIT:
  282.                if(ret) {
  283.                     /* An error occured or attempting to use demo DLL twice */
  284.                     MessageBox(hWndMain,"Could not perform requested operation or using demo DLL twice","ERROR OCCURED",MB_OK);
  285.                    GlobalFree(Frame.hPicture);
  286.             }
  287.                else {
  288.                 /* free the old FRAME and copy the temporary Frame to old FRAME */
  289.                 FreeFrame(DemoPic[nActivePic].Frame);
  290.                 memcpy(&DemoPic[nActivePic].Frame, &Frame, sizeof(FRAME));
  291.                 if(fRemap) BuildPalette(&DemoPic[nActivePic].Frame);
  292.                 /* force the repaint */
  293.                 InvalidateRect(DemoPic[nActivePic].hWndPic,NULL,TRUE);
  294.                }
  295.             break;
  296.           case IDM_O_PICINFO:
  297.             /* Create Dialog Box for picture information */
  298.                lpfnDlgProc=MakeProcInstance(PicInfoDlgProc, hInst);
  299.                DialogBox(hInst, "PICINFOBOX", hWndMain, lpfnDlgProc);
  300.                FreeProcInstance(lpfnDlgProc);
  301.             break; 
  302.           case IDM_O_REMAP:
  303.           /* Enable remap on load */
  304.                fRemap=!fRemap;
  305.                CheckActiveWindow();
  306.                break;
  307.           case IDM_O_CONVERT256NONE:
  308.                /* convert picture from true color (24 bits) to 256 colors (8 bits) */
  309.             if(nActivePic>=0) {
  310.                     /* Convert frame from PICTURE structure to temporary FRAME Frame */
  311.                 if(MapTo8Bit(&DemoPic[nActivePic].Frame, &Frame)) goto DITHER_ERR;
  312.                     /* free the old FRAME and copy the temporary Frame to old FRAME */
  313.                 GlobalFree(DemoPic[nActivePic].Frame.hPicture);
  314.                 memcpy(&DemoPic[nActivePic].Frame, &Frame, sizeof(FRAME));
  315.                 /* force the repaint */
  316.                 InvalidateRect(DemoPic[nActivePic].hWndPic,NULL,TRUE);
  317.             }
  318.             SetCursor(hCursorNormal);
  319.                return 0L;
  320. DITHER_ERR:
  321.                if(DemoPic[nActivePic].Frame.hPalette) GlobalUnlock(DemoPic[nActivePic].Frame.hPalette);
  322.             MessageBox(hWndMain,"Could not convert image!","ERROR OCCURED",MB_OK);
  323.             SetCursor(hCursorNormal);
  324.                return 0L;
  325.  
  326.             case IDM_H_ABOUT:
  327.                /* Create About Dialog Box */
  328.                lpfnDlgProc=MakeProcInstance(AboutDlgProc, hInst);
  329.                DialogBox(hInst, "ABOUTBOX", hWndMain, lpfnDlgProc);
  330.             FreeProcInstance(lpfnDlgProc);
  331.             break;
  332.  
  333.          default:
  334.                 SetCursor(hCursorNormal);
  335.                 return DefWindowProc(hWnd, Message, wParam, lParam);
  336.            }
  337.           SetCursor(hCursorNormal);
  338.          break;        /* End of WM_COMMAND                             */
  339.  
  340.     case WM_CREATE:
  341.  
  342.  
  343.       break;       /*  End of WM_CREATE                              */
  344.  
  345.     case WM_MOVE:     /*  code for moving the window                    */
  346.       break;
  347.     
  348.     case WM_SIZE:     /*  code for sizing client area                   */
  349.       break;       /* End of WM_SIZE                                 */
  350.  
  351.     case WM_PAINT:    /* code for the window's client area              */
  352.       /* Obtain a handle to the device context                       */
  353.       /* BeginPaint will sends WM_ERASEBKGND if appropriate          */
  354.       memset(&ps, 0x00, sizeof(PAINTSTRUCT));
  355.       hDC = BeginPaint(hWnd, &ps);
  356.  
  357.       /* Included in case the background is not a pure color         */
  358.       SetBkMode(hDC, TRANSPARENT);
  359.  
  360.       /* Inform Windows painting is complete                         */
  361.       EndPaint(hWnd, &ps);
  362.       break;       /*  End of WM_PAINT                               */
  363.  
  364.     case WM_CLOSE:  /* close the window                                 */
  365.       /* Destroy child windows, modeless dialogs, then, this window  */
  366.       DestroyWindow(hWnd);
  367.      if (hWnd == hWndMain)
  368.       PostQuitMessage(0);  /* Quit the application                 */
  369.      break;
  370.  
  371.     default:
  372.       /* For any message for which you don't specifically provide a  */
  373.       /* service routine, you should return the message to Windows   */
  374.       /* for default message processing.                             */
  375.       return DefWindowProc(hWnd, Message, wParam, lParam);
  376.    }
  377.  return 0L;
  378. }     /* End of WndProc
  379.                            */
  380. /* This procedure is service routine for one picture window */
  381. LONG FAR PASCAL PicWndProc(HWND hWnd, WORD Message, WORD wParam, LONG lParam)
  382. {
  383.  HDC        hDC;                /* handle for the display device       */
  384.  PAINTSTRUCT ps;                /* holds PAINT information             */
  385.  RECT     rec;
  386.  short      index,nPos,scroller,nWidth,nHeight;
  387.  short    delta,scrr,scr0,scrx,scry, *dim;
  388.  
  389.  GetClientRect(hWnd,&rec);
  390.  index=1000-GetDlgCtrlID(hWnd);
  391.  nPos=LOWORD(lParam);
  392.  /* Folowing code handles the scroll boxes */
  393.  if((Message==WM_HSCROLL) || (Message==WM_VSCROLL)) {
  394.     scroller=(Message==WM_HSCROLL)?SB_HORZ:SB_VERT;
  395.     dim=(Message==WM_HSCROLL)?&(DemoPic[nActivePic].Frame.iWidth):&(DemoPic[nActivePic].Frame.iHeight);
  396.      GetScrollRange(hWnd,SB_HORZ,&scr0,&scrr);
  397.      switch (wParam) {
  398.      case SB_BOTTOM:
  399.           nPos=0;
  400.        break;
  401.      case SB_TOP:
  402.           nPos=scrr;
  403.        break;
  404.      case SB_LINEDOWN:
  405.         nPos=(GetScrollPos(hWnd, scroller)+(*dim)/10);
  406.        break;
  407.      case SB_PAGEDOWN:
  408.         nPos=(GetScrollPos(hWnd, scroller)+(*dim)/2);
  409.        break;
  410.      case SB_LINEUP:
  411.         nPos=(GetScrollPos(hWnd, scroller)-(*dim)/10);
  412.       break;
  413.      case SB_PAGEUP:
  414.         nPos=(GetScrollPos(hWnd, scroller)-(*dim)/2);
  415.        break;
  416.      }
  417.      if(nPos<0) nPos=0;
  418.      else if(nPos>scrr) nPos=scrr;
  419.  }
  420.  switch (Message)
  421.    {
  422.     case WM_SYSCOMMAND:
  423.           switch(wParam) {
  424.           case IDM_CLOSE:
  425.           case SC_CLOSE:
  426.             /* close the main window */
  427.             SendMessage(hWnd, WM_CLOSE, 0, 0L);
  428.                break;
  429.           default:
  430.                return DefWindowProc(hWnd, Message, wParam, lParam);
  431.           }
  432.        break;
  433.     case WM_HSCROLL:
  434.           if((wParam!=SB_ENDSCROLL) && (wParam!=SB_THUMBTRACK)) {
  435.                delta=DemoPic[index].Frame.iWidth-(rec.right-rec.left);
  436.             if(delta<0) nPos=0;
  437.                SetScrollPos(hWnd, SB_HORZ, nPos, TRUE);
  438.                DemoPic[index].offx=delta*nPos/(scrr+1);
  439.                InvalidateRect(hWnd, NULL, TRUE);
  440.        }
  441.           break;
  442.     case WM_VSCROLL:
  443.           if((wParam!=SB_ENDSCROLL) && (wParam!=SB_THUMBTRACK)) {
  444.                delta=DemoPic[index].Frame.iHeight-(rec.bottom-rec.top);
  445.                if(delta<0) nPos=0;
  446.                SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
  447.                DemoPic[index].offy=delta*nPos/(scrr+1);
  448.                InvalidateRect(hWnd, NULL, TRUE);
  449.        }
  450.           break;
  451.     case WM_CREATE:
  452.  
  453.  
  454.          break;       /*  End of WM_CREATE                              */
  455.  
  456.     case WM_MOVE:     /*  code for moving the window                    */
  457.          break;
  458.  
  459.     case WM_ACTIVATE:
  460.          if(hActive) SendMessage(hActive,WM_NCACTIVATE,FALSE,0);
  461.          hActive=hWnd;
  462.          nActivePic=index;
  463.          SendMessage(hActive,WM_NCACTIVATE,TRUE,0);
  464.          return DefWindowProc(hWnd, Message, wParam, lParam);
  465.  
  466.     case WM_SIZE:     /*  code for sizing client area                   */
  467.          if(wParam==SIZE_RESTORED) {
  468.                nWidth=LOWORD(lParam);
  469.                nHeight=HIWORD(lParam);
  470.                if(nWidth>DemoPic[index].Frame.iWidth)
  471.                     nWidth=DemoPic[index].Frame.iWidth;
  472.                if(nHeight>DemoPic[index].Frame.iHeight)
  473.                     nHeight=DemoPic[index].Frame.iHeight;
  474.                scrx=DemoPic[index].Frame.iWidth-nWidth;
  475.                scry=DemoPic[index].Frame.iHeight-nHeight;
  476.                 SetScrollRange(hWnd,SB_HORZ,0,scrx,TRUE);
  477.                SetScrollRange(hWnd,SB_VERT,0,scry,TRUE);
  478.                DemoPic[index].offx=DemoPic[index].offy=0;
  479. //                      MoveWindow(hWnd, 0, 0, nWidth, nHeight, TRUE);
  480. //                      SetWindowPos(hWnd, 0, 0, 0, nWidth, nHeight, SWP_NOMOVE | SWP_NOZORDER);
  481.          }
  482.          break;       /* End of WM_SIZE                                 */
  483.  
  484.     case WM_LBUTTONDOWN:
  485.             SetWindowPos(hWnd,HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  486. //          SendMessage(hWnd,WM_NCLBUTTONDOWN,0,0L);
  487.         SendMessage(hActive,WM_ACTIVATE,TRUE,0);
  488.         break;
  489.  
  490.     case WM_NCLBUTTONDOWN:
  491.          SendMessage(hWnd,WM_ACTIVATE,0,0L);
  492.          return DefWindowProc(hWnd, Message, wParam, lParam);
  493.  
  494.     case WM_PAINT:    /* code for the window's client area              */
  495.       /* Obtain a handle to the device context                       */
  496.       /* BeginPaint will sends WM_ERASEBKGND if appropriate          */
  497.       memset(&ps, 0x00, sizeof(PAINTSTRUCT));
  498.       hDC = BeginPaint(hWnd, &ps);
  499.          /* Included in case the background is not a pure color         */
  500.          SetBkMode(hDC, TRANSPARENT);
  501.          DisplayPicture(index,hDC);
  502.  
  503.       /* Inform Windows painting is complete                         */
  504.       EndPaint(hWnd, &ps);
  505.       break;       /*  End of WM_PAINT                               */
  506.  
  507.     case WM_CLOSE:  /* close the picture window                                 */
  508.          DemoPic[index].hWndPic=0;
  509.          FreeFrame(DemoPic[index].Frame);
  510.          hActive=0;nActivePic=-1;
  511.          DestroyWindow(hWnd);
  512.          CheckActiveWindow();
  513.          break;
  514.  
  515.     default:
  516.       return DefWindowProc(hWnd, Message, wParam, lParam);
  517.    }
  518.  return 0L;
  519. }
  520.  
  521. /* Service routine for About dialog */
  522. BOOL FAR PASCAL AboutDlgProc (HWND hDlg, WORD Message, WORD wParam, LONG lParam) {
  523.      switch(Message) {
  524.           case WM_INITDIALOG:
  525.                return TRUE;
  526.           case WM_COMMAND:
  527.             if(wParam==IDOK) {
  528.                     EndDialog(hDlg,0);
  529.                     return TRUE;
  530.                }
  531.      }
  532.      return FALSE;
  533. }
  534.  
  535. /* Service routine for Picture info dialog */
  536. BOOL FAR PASCAL PicInfoDlgProc (HWND hDlg, WORD Message, WORD wParam, LONG lParam) {
  537.      char buf[256];
  538.      switch(Message) {
  539.           case WM_INITDIALOG:
  540.                GetWindowText(DemoPic[nActivePic].hWndPic, buf, 15);
  541.                SetDlgItemText(hDlg, IDD_PI_FILENAME, buf);
  542.             sprintf(buf, "%d x %d", DemoPic[nActivePic].Frame.iWidth, DemoPic[nActivePic].Frame.iHeight);
  543.                SetDlgItemText(hDlg, IDD_PI_DIMENSION, buf);
  544.                SetDlgItemInt(hDlg, IDD_PI_BITCOUNT,DemoPic[nActivePic].Frame.iNumBits,FALSE);
  545.                if(DemoPic[nActivePic].Frame.iNumBits==8)
  546.                 SetDlgItemInt(hDlg, IDD_PI_PICSIZE, ((long)DemoPic[nActivePic].Frame.iWidth*(long)DemoPic[nActivePic].Frame.iHeight+256L)/1000,FALSE);
  547.                else
  548.                     SetDlgItemInt(hDlg, IDD_PI_PICSIZE, (long)DemoPic[nActivePic].Frame.iWidth*(long)DemoPic[nActivePic].Frame.iHeight*3L/1000,FALSE);
  549.             if(DemoPic[nActivePic].Frame.hPalette)
  550.                 SetDlgItemInt(hDlg, IDD_PI_PALENTRIES, DemoPic[nActivePic].Frame.nPalEntries,FALSE);
  551.             else
  552.                 EnableWindow(GetDlgItem(hDlg, IDD_PI_PALENTRIES), FALSE);
  553.             if(IS_ANIMATION_TYPE(DemoPic[nActivePic].FileInfo.wFileType))
  554.                 SetDlgItemInt(hDlg, IDD_PI_NFRAMES, DemoPic[nActivePic].FileInfo.nFrames,FALSE);
  555.             else
  556.                 EnableWindow(GetDlgItem(hDlg, IDD_PI_NFRAMES), FALSE);
  557.             SetDlgItemText(hDlg, IDD_PI_TYPE, szFileExt[DemoPic[nActivePic].FileInfo.wFileType]+1);
  558.             return TRUE;
  559.           case WM_COMMAND:
  560.                 if(wParam==IDOK) {
  561.                     EndDialog(hDlg,0);
  562.                     return TRUE;
  563.                }
  564.     }
  565.      return FALSE;
  566. }
  567.  
  568. /* Service routine for Frame select dialog */
  569. BOOL FAR PASCAL FrameSelectDlgProc (HWND hDlg, WORD Message, WORD wParam, LONG lParam) {
  570.      switch(Message) {
  571.           case WM_INITDIALOG:
  572.             SetDlgItemInt(hDlg, IDD_FS_START, 1, FALSE);
  573.             SetDlgItemInt(hDlg, IDD_FS_END, nAniFrames, FALSE);
  574.             SetDlgItemInt(hDlg, IDD_FS_MAX, nAniFrames, FALSE);
  575.             return TRUE;
  576.         case WM_COMMAND:
  577.             switch(wParam) {
  578.             case IDOK:
  579.                 iStartFrame=GetDlgItemInt(hDlg, IDD_FS_START,NULL,FALSE);
  580.                 iEndFrame=GetDlgItemInt(hDlg, IDD_FS_END,NULL,FALSE);
  581.                 if(iStartFrame<1 || iStartFrame>iEndFrame || iEndFrame>nAniFrames) {
  582.                     MessageBox(hWndMain,"Illegal values !!", "Input ERROR", MB_ICONEXCLAMATION | MB_OK);
  583.                     SetDlgItemInt(hDlg, IDD_FS_END, nAniFrames, FALSE);
  584.                     SetDlgItemInt(hDlg, IDD_FS_MAX, nAniFrames, FALSE);
  585.                 }
  586.                     else
  587.                         EndDialog(hDlg,1);
  588.                 return TRUE;
  589.             case IDCANCEL:
  590.                 EndDialog(hDlg,0);
  591.                 return FALSE;
  592.             }
  593.      }
  594.     return FALSE;
  595. }
  596.  
  597. /************************************************************************/
  598. /*                                                                      */
  599. /* nCwRegisterClasses Function                                          */
  600. /*                                                                      */
  601. /* The following function registers all the classes of all the windows  */
  602. /* associated with this application. The function returns an error code */
  603. /* if unsuccessful, otherwise it returns 0.                             */
  604. /*                                                                      */
  605. /************************************************************************/
  606.  
  607. short nCwRegisterClasses(void)
  608. {
  609.  WNDCLASS   wndclass;    /* struct to define a window class             */
  610.  memset(&wndclass, 0x00, sizeof(WNDCLASS));
  611.  
  612.  
  613.  /* load WNDCLASS with window's characteristics                         */
  614.  wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW;
  615.  wndclass.lpfnWndProc = WndProc;
  616.  /* Extra storage for Class and Window objects                          */
  617.  wndclass.cbClsExtra = 0;
  618.  wndclass.cbWndExtra = 0;
  619.  wndclass.hInstance = hInst;
  620.  wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  621.  wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  622.  /* Create brush for erasing background                                 */
  623.  wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  624.  wndclass.lpszMenuName = szAppName;   /* Menu Name is App Name */
  625.  wndclass.lpszClassName = szAppName; /* Class Name is App Name */
  626.  if(!RegisterClass(&wndclass))
  627.    return -1;
  628.  wndclass.lpfnWndProc = PicWndProc;
  629.  wndclass.lpszMenuName = NULL;   /* Menu Name is App Name */
  630.  wndclass.lpszClassName = "PICTURE"; /* Class Name is App Name */
  631.  if(!RegisterClass(&wndclass))
  632.    return -1;
  633.  
  634.  
  635.  return(0);
  636. } /* End of nCwRegisterClasses                                          */
  637.  
  638. /************************************************************************/
  639. /*  CwUnRegisterClasses Function                                        */
  640. /*                                                                      */
  641. /*  Deletes any refrences to windows resources created for this         */
  642. /*  application, frees memory, deletes instance, handles and does       */
  643. /*  clean up prior to exiting the window                                */
  644. /*                                                                      */
  645. /************************************************************************/
  646.  
  647. void CwUnRegisterClasses(void)
  648. {
  649.  WNDCLASS   wndclass;    /* struct to define a window class             */
  650.  memset(&wndclass, 0x00, sizeof(WNDCLASS));
  651.  
  652.  UnregisterClass("PICTURE", hInst);
  653.  UnregisterClass(szAppName, hInst);
  654. }    /* End of CwUnRegisterClasses                                      */
  655.  
  656.  
  657. /* Folowing function performs loading (mode==1) and saving (mode==3) of
  658.    pictures */
  659. void LoadSaveData(short mode) {
  660.     ERR_RETURN ret=0,ret1;
  661.     short i,nPN,n;
  662.      char  buf[64],buf1[64];
  663.     FARPROC lpfnDlgProc=NULL;
  664.     LPFRAME lpFrame;
  665.      LPFILEINFO lpFileInfo;
  666.      szFile[0] = '\0';
  667.      szFileTitle[0] = '\0';
  668.  
  669.      switch (mode) {
  670.      case 3:
  671.         /* Fill common dialog OPENFILENAME structure */
  672.         ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
  673.           ofn.lpstrFilter = szFilterSave;
  674.           ofn.nFilterIndex= DemoPic[nActivePic].FileInfo.wFileType;
  675.         GetWindowText(DemoPic[nActivePic].hWndPic, szFile, 9);
  676.           strcat(szFile, szFileExt[DemoPic[nActivePic].FileInfo.wFileType]);
  677.  
  678.         /* Prepare calling parametars */
  679.         lpFrame=&DemoPic[nActivePic].Frame;
  680.           lpFileInfo=&DemoPic[nActivePic].FileInfo;
  681.         if (GetSaveFileName(&ofn) && ofn.nFilterIndex) {
  682.                SetCursor(hCursorBusy);
  683.                /* Fill FileInfo structure...*/
  684.                _fstrncpy(lpFileInfo->szFileName, szFile, MAX_FILE_NAME);
  685.                lpFileInfo->wFileType=ofn.nFilterIndex;
  686.             lpFileInfo->wCompression=0;
  687.             lpFileInfo->nFrames=1;
  688.  
  689.             if(lpFileInfo->wFileType==JPG_FILE)
  690.                 lpFileInfo->wCompression=20; //JPEG save-quality
  691.             /* Save picture...*/
  692.                /* If user selected FLC or FLI type ...*/
  693.             if(IS_ANIMATION_TYPE(lpFileInfo->wFileType)) {
  694.                 if(access(szFile,0)==-1)
  695.                         /* If animation doesn't exist, create one */
  696.                          ret=ImageSave(lpFileInfo, lpFrame);
  697.                 else
  698.                         /* Else append at the end */
  699.                          ret=FLXAppend(lpFileInfo, &lpFrame, 1);
  700.             }
  701.                /* or for all other image types ...*/
  702.             else
  703.                     ret=ImageSave(lpFileInfo, lpFrame);
  704.           }
  705.           break;
  706.      case 1:
  707.           if((nPN=FindEmptySlot())==-1) 
  708.             goto ERR_LABEL;
  709.           /* Fill common dialog OPENFILENAME structure */
  710.         ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  711.         ofn.lpstrFilter = szFilterOpen;
  712.           /* Prepare calling parametars */
  713.         lpFrame=&DemoPic[nPN].Frame;
  714.         lpFileInfo=&DemoPic[nPN].FileInfo;
  715.           if (GetOpenFileName(&ofn) && ofn.nFilterIndex) {
  716.                SetCursor(hCursorBusy);
  717.                /* Fill FileInfo structure...*/
  718.                _fstrncpy(lpFileInfo->szFileName, szFile, MAX_FILE_NAME);
  719.                lpFileInfo->wFileType=ofn.nFilterIndex;
  720.                /* Load picture...*/
  721.                /* If animation type is called (FLI or FLC) */
  722.             if(IS_ANIMATION_TYPE(lpFileInfo->wFileType)) {
  723.                 DemoPic[nPN].hWndPic=1;
  724.                 if(ret=FLXGetInfo(lpFileInfo, lpFrame)) goto ERR_LABEL;
  725.                 nAniFrames=lpFileInfo->nFrames;
  726.                 lpfnDlgProc=MakeProcInstance(FrameSelectDlgProc, hInst);
  727.                 if(DialogBox(hInst, "FRAMESELBOX", hWndMain, lpfnDlgProc)==0) goto ERR_LABEL;
  728.                 File2Name(buf, szFileTitle);
  729.                 nAniFrames=iEndFrame-iStartFrame+1;
  730.                 /* Copy all PICTURE data to each animation FRAME (width and height) */
  731.                     /* and fill AniFrames array with LPFRAME pointers */
  732.                 for(i=0;i<nAniFrames;i++) {
  733.                          /* Find the place for the new picture...*/
  734.                     if((n=FindEmptySlot())==-1)
  735.                         goto ERR_LABEL;
  736.                     AniFrames[i]=&DemoPic[n].Frame;
  737.                     memcpy(&DemoPic[n],&DemoPic[nPN],sizeof(PICTURE));
  738.                          /* Put new window name */
  739.                     sprintf(buf1,"%8s#%d",buf,iStartFrame+i);
  740.                          /* Create new picture window */
  741.                     NewPicture(n, buf1);
  742.                 }
  743.                 if(ret=FLXLoad(lpFileInfo, AniFrames, iStartFrame-1, iEndFrame-1)) goto ERR_LABEL;
  744.                 DemoPic[nPN].hWndPic=0;
  745.                 break;
  746.             }
  747.                /* Load image into *lpFrame */
  748.             else if(ret=ImageLoad(lpFileInfo, lpFrame, 0)) goto ERR_LABEL;
  749.             if(fRemap) BuildPalette(&DemoPic[nPN].Frame);
  750.                File2Name(buf, szFileTitle);
  751.                NewPicture(nPN, buf);
  752.         }
  753.           break;
  754.      }
  755. ERR_LABEL:
  756.     if(ret) {
  757.          if(ret==0xFFFF)
  758.             MessageBox(hWndMain,"...but this is only demo version.","Sorry...",MB_OK | MB_ICONEXCLAMATION);
  759.         else
  760.             for(i=0;i<16;i++)
  761.                    if(ret1=ret&(1<<i))
  762.                         if(LoadString(hInst, ret1, buf, 64))
  763.                              MessageBox(hWndMain,buf,"Return Value",MB_OK);
  764.                         else
  765.                              MessageBox(hWndMain,"Unexpectable error","Return Value",MB_OK);
  766.     }
  767.     if(lpfnDlgProc) FreeProcInstance(lpfnDlgProc);
  768.     return;
  769. }
  770.  
  771. /* This function creates a window for the new picture */
  772. void NewPicture(short nPN, LPSTR szTitle) {
  773.      BOOL vs,hs;
  774.      HMENU hSysMenu;
  775.      short off,bordx,bordy,WW,WH,i;
  776.      RECT    rec;
  777.      DemoPic[nPN].offx= DemoPic[nPN].offy=0;
  778.      GetClientRect(hWndMain, &rec);
  779.      WW=rec.right-rec.left;
  780.      WH=rec.bottom-rec.top;
  781.      bordy=GetSystemMetrics(SM_CYFRAME);
  782.      bordx=GetSystemMetrics(SM_CXFRAME);
  783.      off=GetSystemMetrics(SM_CYCAPTION);
  784.      hs=DemoPic[nPN].Frame.iWidth+off*nPN+bordx > WW;
  785.      vs=DemoPic[nPN].Frame.iHeight+off*(nPN+1)+bordy > WH;
  786.      DemoPic[nPN].hWndPic=CreateWindow(
  787.           "PICTURE", szTitle,
  788.           WS_CHILD | WS_VISIBLE | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CAPTION | WS_THICKFRAME,
  789.           off*nPN,off*nPN,
  790.           hs?(WW-off*nPN):DemoPic[nPN].Frame.iWidth+bordx*2,
  791.           vs?(WH-off*nPN):DemoPic[nPN].Frame.iHeight+off+bordy*2,
  792.           hWndMain, 1000-nPN, hInst, NULL);
  793.      hSysMenu=GetSystemMenu(DemoPic[nPN].hWndPic, FALSE);
  794.      DeleteMenu(hSysMenu, 0, MF_BYPOSITION);
  795.      for(i=0;i<6;i++) DeleteMenu(hSysMenu, 2, MF_BYPOSITION);
  796.      AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);
  797.      AppendMenu(hSysMenu, MF_STRING, IDM_CLOSE, "&Close  Ctrl+F4");
  798.      nActivePic=nPN;
  799.      SetWindowPos(DemoPic[nPN].hWndPic,HWND_TOP,
  800.           0 , 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
  801.      SendMessage(DemoPic[nPN].hWndPic,WM_ACTIVATE,TRUE,0L);
  802. }
  803.  
  804. /* This function handles Paint message for picture window */
  805. void DisplayPicture(short i, HDC hDC) {
  806.      LPHBYTE         lpBitmap;
  807.      PBITMAPINFO     pbmi;
  808.      HANDLE          hloc;
  809.      BYTE            tmp;
  810.      PALETTEENTRY FAR *lpPal;
  811.      short           j;
  812.  
  813.      if(lpBitmap = GlobalLock(DemoPic[i].Frame.hPicture)) {
  814.           hDC=GetDC(DemoPic[i].hWndPic);
  815.           if(DemoPic[i].Frame.hPalette) SelectPalette(hDC,DemoPic[i].Frame.hPalette,FALSE);
  816.         RealizePalette(hDC);
  817.           /* if the picture is 8 bit */
  818.         if(DemoPic[i].Frame.iNumBits==8) {
  819.                if((hloc = LocalAlloc(LMEM_ZEROINIT | LMEM_FIXED,DemoPic[i].Frame.nPalEntries*sizeof(PALETTEENTRY)+sizeof(BITMAPINFOHEADER)))==NULL)
  820.           goto ERR_LABEL;
  821.                if((pbmi = (PBITMAPINFO) LocalLock(hloc))==NULL)
  822.                     goto ERR_LABEL;
  823.                lpPal=(PALETTEENTRY FAR*)pbmi->bmiColors;
  824.             GetPaletteEntries(DemoPic[i].Frame.hPalette,0,DemoPic[i].Frame.nPalEntries,lpPal);
  825.                for(j=0;j<DemoPic[i].Frame.nPalEntries;j++) {
  826.                     tmp=lpPal[j].peBlue;                    
  827.                     lpPal[j].peBlue=lpPal[j].peRed;
  828.                     lpPal[j].peRed=tmp;
  829.             }
  830.                pbmi->bmiHeader.biBitCount =8;
  831.                pbmi->bmiHeader.biClrImportant = 0;
  832.                pbmi->bmiHeader.biClrUsed = DemoPic[i].Frame.nPalEntries;
  833.  
  834.           }       
  835.           else {
  836.         /* if the picture is 24 bit */
  837.             if((hloc = LocalAlloc(LMEM_ZEROINIT | LMEM_MOVEABLE,sizeof(BITMAPINFOHEADER)))==NULL)
  838.           goto ERR_LABEL;
  839.                if((pbmi = (PBITMAPINFO) LocalLock(hloc))==NULL)
  840.                     goto ERR_LABEL;
  841.                pbmi->bmiHeader.biBitCount = 24; 
  842.                pbmi->bmiHeader.biClrUsed = 0;
  843.         }
  844.         /* Fill the BITMAPINFOHEADER structure */
  845.         pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  846.           pbmi->bmiHeader.biWidth = DemoPic[i].Frame.iWidth;
  847.           pbmi->bmiHeader.biHeight = DemoPic[i].Frame.iHeight;
  848.           pbmi->bmiHeader.biPlanes = 1;
  849.         pbmi->bmiHeader.biCompression = BI_RGB;
  850.           /* Draw the picture */
  851.           SetDIBitsToDevice(hDC, -DemoPic[i].offx, -DemoPic[i].offy, ROUND2LONG(DemoPic[i].Frame.iWidth), DemoPic[i].Frame.iHeight,
  852.                     0, 0, 0, DemoPic[i].Frame.iHeight, lpBitmap, pbmi, DIB_RGB_COLORS);
  853.           GlobalUnlock(DemoPic[i].Frame.hPicture);
  854.      }
  855. ERR_LABEL:
  856.      if(hloc) {
  857.         LocalUnlock(hloc);
  858.           LocalFree(hloc);
  859.      }
  860.      ReleaseDC(DemoPic[i].hWndPic, hDC);
  861.      fPaintEnd=TRUE;
  862. }
  863.  
  864. /* Cut off the extension */
  865. void File2Name(LPSTR dest, LPSTR source) {
  866.      for(;*source && *source!='.';*(dest++)=*(source++));
  867.      *dest='\0';
  868. }
  869.  
  870. /* Check the menu visibility */
  871. void CheckActiveWindow() {
  872.      short i;
  873.      HMENU hSubMenu;
  874.      hSubMenu=GetSubMenu(hMenu,1);
  875.      if(nActivePic==-1) {
  876.           EnableMenuItem(hMenu, IDM_F_SAVEPICTURE, MF_BYCOMMAND | MF_GRAYED);
  877.           EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);
  878.           EnableMenuItem(hSubMenu, 0, MF_BYPOSITION | MF_GRAYED);
  879.           EnableMenuItem(hSubMenu, 2, MF_BYPOSITION | MF_GRAYED);
  880.         if(hActive=GetWindow(hWndMain, GW_CHILD))
  881.                for(i=0;i<MAX_NUM_PIC;i++)
  882.                     if(hActive==DemoPic[i].hWndPic) {
  883.                        nActivePic=i;
  884.                          SendMessage(DemoPic[i].hWndPic,WM_ACTIVATE,TRUE,0L);
  885.                          goto LAB01;
  886.                     } 
  887.      }
  888.      else {
  889. LAB01:
  890.      if(DemoPic[nActivePic].Frame.iNumBits==24)
  891.                EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);
  892.           else
  893.                EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);
  894.           EnableMenuItem(hMenu, IDM_F_SAVEPICTURE, MF_BYCOMMAND | MF_ENABLED);
  895.           EnableMenuItem(hSubMenu, 0, MF_BYPOSITION | MF_ENABLED);
  896.           EnableMenuItem(hSubMenu, 2, MF_BYPOSITION | MF_ENABLED);
  897.      }
  898.      CheckMenuItem(hMenu, IDM_O_REMAP, fRemap?MF_CHECKED:MF_UNCHECKED);
  899.  
  900.      DrawMenuBar(hWndMain);
  901. }
  902.  
  903. /* Place the new picture in the DemoPic array if possible */
  904. short FindEmptySlot() {
  905.      short i;
  906.      for(i=0;i<nPicNum;i++) 
  907.           if(DemoPic[i].hWndPic==0) {
  908.             memset(&(DemoPic[i]),0,sizeof(PICTURE));
  909.             return i;
  910.           }
  911.      if(nPicNum+1>=MAX_NUM_PIC) {
  912.           MessageBox(hWndMain,"Too many windows opened","ERROR",MB_OK | MB_ICONEXCLAMATION);
  913.           return -1;
  914.      }
  915.      memset(&(DemoPic[nPicNum++]),0,sizeof(PICTURE));
  916.      return nPicNum-1;
  917. }
  918.