📄 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 instanceTCHAR szTitle[MAX_LOADSTRING]; // The title bar textTCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text// List of files to display and pointer to current fileLPTSTR 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_SUPPORTvoid _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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -