Logo Search packages:      
Sourcecode: giflib version File versions

gifshow.cpp

// gifshow.cpp : Defines the entry point for the application.
//
// Simple test program for testing CGIFWin class.  Skeleton Windows
// application generated by Microsoft Visual C++.
//
//    Licensed under the terms laid out in the libungif COPYING file.
//
// Usage:
//   pass the GIF file as a command-line parameter or drag-and-drop
//   files from Explorer onto the main window
//
// Known Limitations:
//   1. Does not support palette messages so
//          test only on 16-bit/24-bit color

#include "stdafx.h"
#include <windowsx.h>
#include <process.h>
#include <shellapi.h>
#include "resource.h"
#include "GifWin.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                            // current instance
TCHAR szTitle[MAX_LOADSTRING];                              // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];                  // The title bar text

// List of files to display and pointer to current file
LPTSTR pszFileList = NULL;
LPTSTR pszCurrentFile = NULL;

int iViewScale = 0;                             // View size (-1=50, 0=100, 1=200)
BOOL bAnimate = TRUE;
HANDLE hFrameEvent = NULL;

// Foward declarations of functions included in this code module:
ATOM                    MyRegisterClass(HINSTANCE hInstance);
BOOL                    InitInstance(HINSTANCE, int);
LRESULT CALLBACK  WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK  About(HWND, UINT, WPARAM, LPARAM);


CGIFWin gif;


HWND ghwndGIF = NULL;

#define PALETTE_SUPPORT

#ifdef PALETTE_SUPPORT
      HPALETTE hPalette = NULL;
#endif // PALETTE_SUPPORT

void _cdecl DrawGifThread(LPVOID /*pParam*/)
{
      while (ghwndGIF)
      {
            COLORREF rgbBack = ::GetSysColor(COLOR_BTNFACE);

            int iLength = lstrlen(pszCurrentFile);
            if (iLength)
            {
                  // Set Window Title (show filename)
                  TCHAR szWindowTitle[MAX_PATH + MAX_LOADSTRING];
                  ::wsprintf(szWindowTitle, "%s - %s", szTitle, pszCurrentFile);
                  if (ghwndGIF)
                        ::SetWindowText(ghwndGIF, szWindowTitle);
            UINT uLoop = 0;

                  // Draw animated GIF to Windows Device Context (HDC)
                  if (gif.Open(pszCurrentFile, rgbBack) == 0)
                  {
                        while (ghwndGIF)
                        {
                              int delay = gif.NextImage();
                              if (ghwndGIF)
                              {
                                    ::InvalidateRect(ghwndGIF, NULL, FALSE);
                                    ::UpdateWindow(ghwndGIF);
                              }
                              if (delay <= 0)
                              {
                                    TRACE("NextImage() returned %d\n", delay);

                        // Limit loops to 2 loops (3 times)
                        UINT uLoopCount = gif.GetLoopCount();
                        if (uLoopCount > 2)
                            uLoopCount = 2;

                        // Exit loop if loop count expired
                        // or there is an error closing/reopening the file
                        if (++uLoop > uLoopCount)
                            break;

                        TRACE("Loop count=%d\n", uLoop);
                        gif.Close();
                        if (gif.Open(pszCurrentFile, rgbBack) != 0)
                        {
                            break;
                        }
                              }
                    else
                    {
                        ASSERT( hFrameEvent );
                        ::WaitForSingleObject(hFrameEvent, bAnimate ? delay : INFINITE);
                    }
                        }
                        gif.Close();
                        // Skip to next filename
                        pszCurrentFile += (iLength + 1);
                        ::Sleep(500);
                        if (ghwndGIF)
                        {
                              ::SetWindowText(ghwndGIF, szTitle);
                              ::InvalidateRect(ghwndGIF, NULL, TRUE);
                        }
                  }
            }
            else // (iLength == 0)
            {
                  ::DragAcceptFiles(ghwndGIF, TRUE);
            }
      } // while
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE /*hPrevInstance*/,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
      MSG msg;
      HACCEL hAccelTable;

      TRACE("WinMain: lpCmdLine=%s\n", lpCmdLine);

      // Initialize global strings
      LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
      LoadString(hInstance, IDC_GIFSHOW, szWindowClass, MAX_LOADSTRING);
      MyRegisterClass(hInstance);

      // Set current file to command line and convert spaces to separating '\0' nulls
      pszCurrentFile = lpCmdLine;
      LPTSTR pszSep = lpCmdLine;
      while (pszSep)
      {
            pszSep = strchr(pszSep, ' ');
            if (pszSep == NULL)
                  break;
            *pszSep++ = '\0';
      }

      // Perform application initialization:
      if (!InitInstance (hInstance, nCmdShow)) 
      {
            return FALSE;
      }

      hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_GIFSHOW);
    hFrameEvent = ::CreateEvent(NULL, /*bManualReset=*/ FALSE, /*bInitialState=*/ FALSE, _T("frame"));

      // Main message loop:
      while (GetMessage(&msg, NULL, 0, 0)) 
      {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
            {
                  TranslateMessage(&msg);
                  DispatchMessage(&msg);
            }
      }

    CloseHandle(hFrameEvent);

      return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
      WNDCLASSEX wcex;

      wcex.cbSize = sizeof(WNDCLASSEX); 

      HICON hIcon = (HICON) ::LoadImage(hInstance, MAKEINTRESOURCE(IDI_GIFSHOW), IMAGE_ICON, 16,16, LR_DEFAULTSIZE);

      wcex.style              = CS_HREDRAW | CS_VREDRAW;
      wcex.lpfnWndProc  = (WNDPROC)WndProc;
      wcex.cbClsExtra         = 0;
      wcex.cbWndExtra         = 0;
      wcex.hInstance          = hInstance;
      wcex.hIcon              = hIcon;
      wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
      wcex.hbrBackground      = (HBRUSH)(COLOR_BTNFACE+1);
      wcex.lpszMenuName = (LPCSTR)IDC_GIFSHOW;
      wcex.lpszClassName      = szWindowClass;
      wcex.hIconSm            = hIcon;

      return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, 500, 250, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

void UpdateMenu(HWND hWnd)
{
    HMENU hMenu = GetMenu(hWnd);
    CheckMenuRadioItem(hMenu, IDM_VIEW_25, IDM_VIEW_400, IDM_VIEW_100 + iViewScale, MF_BYCOMMAND);
    CheckMenuItem(hMenu, ID_VIEW_ANIMATE, bAnimate ? MF_CHECKED : MF_UNCHECKED);
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND    - process the application menu
//  WM_PAINT      - Paint the main window
//  WM_DESTROY    - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      int wmId, wmEvent;
      PAINTSTRUCT ps;
      TCHAR szHello[MAX_LOADSTRING];
      LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

      switch (message) 
      {
            case WM_COMMAND:
                  wmId    = LOWORD(wParam); 
                  wmEvent = HIWORD(wParam); 
                  // Parse the menu selections:
                  switch (wmId)
                  {
                        case IDM_ABOUT:
                           DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
                           break;
                        case IDM_VIEW_25:
                        case IDM_VIEW_33:
                        case IDM_VIEW_50:
                        case IDM_VIEW_100:
                        case IDM_VIEW_200:
                        case IDM_VIEW_300:
                        case IDM_VIEW_400:
                    iViewScale = wmId - IDM_VIEW_100;
                    InvalidateRect(hWnd, NULL, TRUE);
                    UpdateMenu(hWnd);
                    break;
                case ID_VIEW_ANIMATE:
                    bAnimate = !bAnimate;
                    UpdateMenu(hWnd);
                    break;
                case ID_VIEW_FRAME:
                    bAnimate = FALSE;
                    if (hFrameEvent)
                        SetEvent(hFrameEvent);
                    UpdateMenu(hWnd);
                    break;
                        case IDM_EXIT:
                           DestroyWindow(hWnd);
                           break;
                        default:
                           return DefWindowProc(hWnd, message, wParam, lParam);
                  }
                  break;
            case WM_DROPFILES:
            {
                  HDROP hDrop = (HDROP) wParam;

                  // Don't accept more dropped files
                  ::DragAcceptFiles(hWnd, FALSE);

                  // Get number of files dropped
                  const int iFiles = ::DragQueryFile(hDrop, ~0U, NULL, 0);

                  // Free previous file list (if allocated)
                  if (pszFileList)
                  {
                        GlobalFreePtr(pszFileList);
                  }

                  // Allocate buffer to hold list of files
                  pszFileList = (LPTSTR) GlobalAllocPtr(GMEM_ZEROINIT, iFiles * MAX_PATH);
                  if (pszFileList)
                  {
                        LPTSTR pFile = pszFileList;
                        for (int iIndex = 0; iIndex < iFiles; ++iIndex)
                        {
                              if (::DragQueryFile(hDrop, iIndex, pFile, MAX_PATH))
                              {
                                    TRACE("WM_DROPFILES (%d of %d) szPathName=%s\n", iIndex, iFiles, pFile);
                                    // Add terminating '\n' between files
                                    int iLength = lstrlen(pFile);
                                    pFile += (iLength + 1);
                              }
                        }
                        *pFile++ = '\0';
                        pszCurrentFile = pszFileList;
                  }
                  DragFinish(hDrop);
                  break;
            }
            case WM_CREATE:
            {
                  HDC hDC = ::GetDC(hWnd);
#ifdef PALETTE_SUPPORT
                  hPalette = ::CreateHalftonePalette(hDC);
#endif // PALETTE_SUPPORT
                  ::ReleaseDC(hWnd, hDC);
                  ghwndGIF = hWnd;
                  _beginthread(DrawGifThread, 0, hWnd);
            UpdateMenu(hWnd);
                  return DefWindowProc(hWnd, message, wParam, lParam);
            }
            case WM_PAINT:
            {     
                  RECT rect;
                  GetClientRect(hWnd, &rect);

                  HDC hDC = BeginPaint(hWnd, &ps);
#ifdef PALETTE_SUPPORT
                  // Select and realize palette (for 8-bit displays)
                  HPALETTE hOldPal = ::SelectPalette(hDC, hPalette, TRUE);
                  ::RealizePalette(hDC);
                  gif.Draw(hDC, &rect, iViewScale);
                  if (hOldPal)
                        ::SelectPalette(hDC, hOldPal, TRUE);
#else
                  gif.Draw(hDC, &rect, iViewScale);
#endif // PALETTE_SUPPORT
                  EndPaint(hWnd, &ps);
                  break;
            }
            case WM_DESTROY:
            {
                  ghwndGIF = NULL;
                  Sleep(1000);                  // Wait for thread to self destruct

                  // Free previous file list (if allocated)
                  if (pszFileList)
                  {
                        TRACE("Free pszFileList!\n");
                        GlobalFreePtr(pszFileList);
                        pszFileList = NULL;
                  }
#ifdef PALETTE_SUPPORT
                  if (hPalette)
                  {
                        TRACE("Delete palette!\n");
                        ::DeleteObject(hPalette);
                        hPalette = NULL;
                  }
#endif // PALETTE_SUPPORT
                  PostQuitMessage(0);
                  break;
            }
            default:
                  return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/)
{
      switch (message)
      {
            case WM_INITDIALOG:
                        return TRUE;

            case WM_COMMAND:
                  if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
                  {
                        EndDialog(hDlg, LOWORD(wParam));
                        return TRUE;
                  }
                  break;
      }
    return FALSE;
}

Generated by  Doxygen 1.6.0   Back to index