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

Windows编程

开发平台:

Visual C++

  1. /****************************************************************************
  2.  *
  3.  *   TxtOut.c
  4.  *
  5.  *   TXTOUT is a sample installable compressor for AVI 1.0.
  6.  *
  7.  ***************************************************************************/
  8. /**************************************************************************
  9.  *
  10.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13.  *  PURPOSE.
  14.  *
  15.  *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  16.  *
  17.  **************************************************************************/
  18. #define INC_OLE2
  19. #include <windows.h>
  20. #include <windowsx.h>
  21. #include <mmsystem.h>
  22. #include <vfw.h>
  23. #include <stdlib.h> // for mbstowcs
  24. #include <memory.h> // for _fmemcpy
  25. #include <stdarg.h> // for va_list
  26. #include "TxtOut.h"
  27. /*****************************************************************************
  28.  *
  29.  *
  30.  ****************************************************************************/
  31. #define MODNAME         "TXTOUT"
  32. #define FOURCC_SAMP mmioFOURCC('D','R','A','W')
  33. #define VERSION_SAMP    0x00010000 // 1.00
  34. extern HANDLE ghModule;
  35. /*****************************************************************************
  36.  *
  37.  * DefaultState holds the compression options that will be used if the user
  38.  * compresses an image without configuring us at all first. In the case of
  39.  * the sample compressor, it is the pixel keep ratio.
  40.  *
  41.  ****************************************************************************/
  42. ICSTATE DefaultState = {2};
  43. /*****************************************************************************
  44.  *
  45.  * Load() is called from the ICM_LOAD message.
  46.  *
  47.  * Tasks such as allocating global memory that is non-instance specific
  48.  * or initializing coprocessor hardware may be performed here.
  49.  *
  50.  * Our simple case needs none of this.
  51.  *
  52.  ****************************************************************************/
  53. BOOL NEAR PASCAL Load(void)
  54. {
  55.     DPF2("Load()");
  56.     return TRUE;
  57. }
  58. /*****************************************************************************
  59.  *
  60.  * Free() is called from the ICM_FREE message.
  61.  *
  62.  * It should totally reverse the effects of Load() in preparation for
  63.  * the DRV being removed from memory.
  64.  *
  65.  ****************************************************************************/
  66. void NEAR PASCAL Free(void)
  67. {
  68.     DPF2("Free()");
  69. }
  70. /*****************************************************************************
  71.  *
  72.  * Open() is called from the ICM_OPEN message
  73.  *
  74.  * This message will be sent for a particular compress/decompress session.
  75.  * Our code must verify that we are indeed being called as a video
  76.  * compressor and create/initialize a state structure. The ICM will
  77.  * give us back the pointer to that structure on every message dealing
  78.  * with this session.
  79.  *
  80.  ****************************************************************************/
  81. INSTINFO * NEAR PASCAL Open(
  82.     ICOPEN FAR * icinfo)
  83. {
  84.     INSTINFO * pinst;
  85.     DPF2("Open('%4.4hs', '%4.4hs')", &icinfo->fccType, &icinfo->fccHandler);
  86.     //
  87.     // refuse to open if we are not being opened as a Video compressor
  88.     //
  89.     if (icinfo->fccType != streamtypeTEXT) {
  90.         DPF2("Open rejected: not TEXT");
  91.         return NULL;
  92.     }
  93.     pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO));
  94.     if (!pinst) {
  95.         icinfo->dwError = ICERR_MEMORY;
  96.         DPF2("Open rejected: no memory");
  97.         return NULL;
  98.     }
  99.     //
  100.     // init structure
  101.     //
  102.     pinst->dwFlags = icinfo->dwFlags;
  103.     pinst->nDraw = 0;
  104.     pinst->hfont = GetStockFont(ANSI_VAR_FONT);
  105.     //
  106.     // set the default state.
  107.     //
  108.     SetState(pinst, NULL, 0);
  109.     //
  110.     // return success.
  111.     //
  112.     icinfo->dwError = ICERR_OK;
  113.     DPF2("Open succeeded!");
  114.     return pinst;
  115. }
  116. /*****************************************************************************
  117.  *
  118.  * Close() is called on the ICM_CLOSE message.
  119.  *
  120.  * This message is the complement to ICM_OPEN and marks the end
  121.  * of a compress/decompress session. We kill any in-progress operations
  122.  * (although this shouldn't be needed) and free our instance structure.
  123.  *
  124.  ****************************************************************************/
  125. LRESULT NEAR PASCAL Close(
  126.     INSTINFO * pinst)
  127. {
  128.     DPF2("Close()");
  129.     while (pinst->nDraw > 0)
  130.         DrawEnd(pinst);
  131.     LocalFree((HLOCAL)pinst);
  132.     return 1;
  133. }
  134. /*****************************************************************************
  135.  *
  136.  * QueryAbout() and About() handle the ICM_ABOUT message.
  137.  *
  138.  * QueryAbout() returns TRUE to indicate we support an about box.
  139.  * About() displays the box.
  140.  *
  141.  ****************************************************************************/
  142. BOOL NEAR PASCAL QueryAbout(
  143.     INSTINFO * pinst)
  144. {
  145.     DPF2("QueryAbout()");
  146.     return TRUE;
  147. }
  148. LRESULT NEAR PASCAL About(
  149.     INSTINFO * pinst,
  150.     HWND hwnd)
  151. {
  152.     char sztempName[50];
  153.     char sztempDesc[50];
  154.     LoadString(ghModule, IDS_NAME, sztempName, sizeof sztempName);
  155.     LoadString(ghModule, IDS_DESCRIPTION, sztempDesc, sizeof sztempDesc);
  156.     DPF2("About()");
  157.     MessageBox(hwnd, sztempDesc, sztempName, MB_OK|MB_ICONINFORMATION);
  158.     return ICERR_OK;
  159. }
  160. /*****************************************************************************
  161.  *
  162.  * QueryConfigure() and Configure() implement the ICM_CONFIGURE message.
  163.  *
  164.  * These functions put up a dialog that allows the user, if he so
  165.  * chooses, to modify the configuration portion of our state info.
  166.  *
  167.  ****************************************************************************/
  168. BOOL NEAR PASCAL QueryConfigure(
  169.     INSTINFO * pinst)
  170. {
  171.     DPF2("QueryConfigure()");
  172.     return FALSE;
  173. }
  174. LRESULT NEAR PASCAL Configure(
  175.     INSTINFO * pinst,
  176.     HWND hwnd)
  177. {
  178.     DPF2("Configure()");
  179.     return DialogBoxParam(ghModule,"Configure",hwnd,ConfigureDlgProc, (LONG)(UINT)pinst);
  180. }
  181. /*****************************************************************************
  182.  *
  183.  * GetState() implements the ICM_GETSTATE message.
  184.  *
  185.  * We copy our configuration information and return how many bytes it took.
  186.  *
  187.  ****************************************************************************/
  188. LRESULT NEAR PASCAL GetState(
  189.     INSTINFO * pinst,
  190.     LPVOID pv,
  191.     DWORD dwSize)
  192. {
  193.     DPF2("GetState(%08lX, %ld)", pv, dwSize);
  194.     if (pv == NULL || dwSize == 0)
  195.         return sizeof(ICSTATE);
  196.     if (dwSize < sizeof(ICSTATE))
  197.         return 0;
  198.     *((ICSTATE FAR *)pv) = pinst->CurrentState;
  199.     // return number of bytes copied
  200.     return sizeof(ICSTATE);
  201. }
  202. /*****************************************************************************
  203.  *
  204.  * SetState() implements the ICM_SETSTATE message.
  205.  *
  206.  * The ICM is giving us configuration information saved by GetState()
  207.  * earlier.
  208.  *
  209.  ****************************************************************************/
  210. LRESULT NEAR PASCAL SetState(
  211.     INSTINFO * pinst,
  212.     LPVOID pv,
  213.     DWORD dwSize)
  214. {
  215.     DPF2("SetState(%08lX, %ld)", pv, dwSize);
  216.     if (pv == NULL)
  217.         pinst->CurrentState = DefaultState;
  218.     else if (dwSize >= sizeof(ICSTATE))
  219.         pinst->CurrentState = *((ICSTATE FAR *)pv);
  220.     else
  221.         return 0;
  222.     // return number of bytes copied
  223.     return sizeof(ICSTATE);
  224. }
  225. /*****************************************************************************
  226.  *
  227.  * GetInfo() implements the ICM_GETINFO message
  228.  *
  229.  * We just fill in the structure to tell the ICM what we can do. The flags
  230.  * (none of which this sample supports) mean the following :
  231.  *
  232.  * VIDCF_QUALITY - we support the quality variable. This means we look at
  233.  *                 dwQuality in the ICINFO structure when compressing and
  234.  *                 make a concious decision to trade quality for space.
  235.  *                 (higher values of dwQuality mean quality is more
  236.  *                 important). dwQuality is set by the ICM.
  237.  *
  238.  * VIDCF_TEMPORAL - We do interframe compression. In this algorithm, not
  239.  *                  every frame is a "key frame"; some frames depend on
  240.  *                  other frames to be generated. An example of this might
  241.  *                  be to store frame buffer differences until the
  242.  *                  differences are big enough to no longer make this
  243.  *                  worthwhile, then storing another complete frame and
  244.  *                  starting over. In this case, the complete frames that
  245.  *                  are stored are key frames and should be flagged as
  246.  *                  such.
  247.  *
  248.  * VIDCF_DRAW -     We will draw the decompressed image on our own. This is
  249.  *                  useful if the decompression is assisted by the video
  250.  *                  hardware.
  251.  *
  252.  ****************************************************************************/
  253. LRESULT NEAR PASCAL GetInfo(
  254.     INSTINFO * pinst,
  255.     ICINFO FAR *icinfo,
  256.     DWORD dwSize)
  257. {
  258.     char sztempName[50];
  259.     char sztempDesc[50];
  260.     LoadString(ghModule, IDS_NAME, sztempName, sizeof sztempName);
  261.     LoadString(ghModule, IDS_DESCRIPTION, sztempDesc, sizeof sztempDesc);
  262.     DPF2("GetInfo()");
  263.     if (icinfo == NULL)
  264.         return sizeof(ICINFO);
  265.     if (dwSize < sizeof(ICINFO))
  266.         return 0;
  267.     icinfo->dwSize      = sizeof(ICINFO);
  268.     icinfo->fccType     = streamtypeTEXT;
  269.     icinfo->fccHandler  = FOURCC_SAMP;
  270.     icinfo->dwFlags     = VIDCF_DRAW;
  271.                 // VIDCF_QUALITY    // supports quality
  272.                 // VIDCF_TEMPORAL   // supports inter-frame
  273.                 // VIDCF_DRAW       // supports drawing
  274.     icinfo->dwVersion   = VERSION_SAMP;
  275.     icinfo->dwVersionICM    = ICVERSION;
  276.     mbstowcs(icinfo->szDescription, sztempDesc, sizeof sztempDesc);
  277.     mbstowcs(icinfo->szName, sztempName, sizeof sztempName);
  278.     return sizeof(ICINFO);
  279. }
  280. LRESULT NEAR PASCAL DrawQuery(
  281.     INSTINFO * pinst,
  282.     LPVOID FAR * lpFormat)
  283. {
  284.     return ICERR_OK;
  285. }
  286. /*****************************************************************************
  287.  *
  288.  * DrawBegin() implements ICM_DRAW_BEGIN
  289.  *
  290.  * This is just like DecompressBegin() except that we also must prepare to
  291.  * actually draw the bitmap on the screen. ICDRAWBEGIN provides info specific
  292.  * to this task.
  293.  *
  294.  ****************************************************************************/
  295. LRESULT NEAR PASCAL DrawBegin(
  296.     INSTINFO * pinst,
  297.     ICDRAWBEGIN FAR *icinfo,
  298.     DWORD dwSize)
  299. {
  300.     DPF2("DrawBegin()");
  301.     if (pinst->nDraw++ > 0)
  302.         return ICERR_OK;
  303.     //
  304.     // get ready to draw
  305.     //
  306.     pinst->db = *icinfo;
  307.     SetRect(&pinst->rc, icinfo->xDst, icinfo->yDst,
  308.         icinfo->xDst + icinfo->dxDst, icinfo->yDst + icinfo->dyDst);
  309.     return ICERR_OK;
  310. }
  311. /*****************************************************************************
  312.  *
  313.  * Draw implements ICM_DRAW
  314.  *
  315.  * Decompress and draw
  316.  *
  317.  ****************************************************************************/
  318. LRESULT NEAR PASCAL Draw(
  319.     INSTINFO * pinst,
  320.     ICDRAW FAR *icinfo,
  321.     DWORD dwSize)
  322. {
  323.     HFONT hfont;
  324.     DPF2("Draw()");
  325.     if (icinfo->lpData && icinfo->cbData) {
  326.         pinst->iLen = min((int) icinfo->cbData,
  327.                 (int) _fstrlen((LPSTR) icinfo->lpData));
  328.         pinst->iLen = min(pinst->iLen, BUFFER_SIZE - 1);
  329.         hmemcpy(pinst->achBuffer, icinfo->lpData, pinst->iLen);
  330.         pinst->achBuffer[pinst->iLen] = '';
  331.     } else if (!(icinfo->dwFlags & ICDRAW_UPDATE))
  332.         return ICERR_OK;
  333.     if (pinst->nDraw == 0)
  334.         return ICERR_ERROR;
  335.     hfont = SelectFont(pinst->db.hdc, pinst->hfont);
  336.     ExtTextOut(pinst->db.hdc,
  337.         pinst->db.xDst, pinst->db.yDst,
  338.         ETO_OPAQUE,
  339.         &pinst->rc,
  340.         (LPSTR) pinst->achBuffer,
  341.         pinst->iLen,
  342.         NULL);
  343.     SelectFont(pinst->db.hdc, hfont);
  344.     return ICERR_OK;
  345. }
  346. /*****************************************************************************
  347.  *
  348.  * DrawEnd() implements ICM_DRAW_END
  349.  *
  350.  * See DecompressEnd()
  351.  *
  352.  ****************************************************************************/
  353. LRESULT NEAR PASCAL DrawEnd(
  354.     INSTINFO * pinst)
  355. {
  356.     DPF2("DrawEnd()");
  357.     if (pinst->nDraw == 0)
  358.         return ICERR_ERROR;
  359.     if (--pinst->nDraw > 0)
  360.         return ICERR_OK;
  361.     //
  362.     // but if we did we would clean up here
  363.     //
  364.     return ICERR_OK;
  365. }
  366. /*****************************************************************************
  367.  *
  368.  * ConfigureDlgProc() is called by Configure
  369.  *
  370.  * This is a standard dialog proc which allows the user to
  371.  * pick config options for the driver.
  372.  *
  373.  ****************************************************************************/
  374. BOOL CALLBACK ConfigureDlgProc(
  375.     HWND hdlg,
  376.     UINT msg,
  377.     WPARAM wParam,
  378.     LPARAM lParam)
  379. {
  380.     switch (msg)
  381.     {
  382.     case WM_COMMAND:
  383.         switch LOWORD((wParam))
  384.         {
  385.             case IDOK:
  386.                 EndDialog(hdlg,TRUE);
  387.                 break;
  388.             case IDCANCEL:
  389.                 EndDialog(hdlg,FALSE);
  390.                 break;
  391.         }
  392.         break;
  393.     }
  394.     return FALSE;
  395. }
  396. /*****************************************************************************
  397.  *
  398.  * dprintf() is called by the DPF macro if DEBUG is defined at compile time.
  399.  *
  400.  * The messages will be send to COM1: like any debug message. To
  401.  * enable debug output, add the following to WIN.INI :
  402.  *
  403.  * [debug]
  404.  * TXTOUT=1
  405.  *
  406.  ****************************************************************************/
  407. #ifdef DEBUG
  408. static int iDebug = -1;
  409. void FAR cdecl dprintf(
  410.     LPSTR szFormat,
  411.     ...)
  412. {
  413.     char ach[128];
  414.     if (iDebug == -1)
  415.         iDebug = GetProfileInt("Debug", MODNAME, FALSE);
  416.     if (!iDebug)
  417.         return;
  418.     lstrcpy(ach, MODNAME ": ");
  419.     {
  420.         va_list va;
  421.         va_start(va, szFormat);
  422.         wvsprintf(ach+lstrlen(ach), szFormat, va);
  423.         va_end(va);
  424.     }
  425.     lstrcat(ach, "rn");
  426.     OutputDebugString(ach);
  427. }
  428. void FAR cdecl dprintf2(
  429.     LPSTR szFormat,
  430.     ...)
  431. {
  432.     char ach[128];
  433.     if (iDebug == -1)
  434.         iDebug = GetProfileInt("Debug", MODNAME, FALSE);
  435.     if (iDebug < 2)
  436.         return;
  437.     lstrcpy(ach, MODNAME ": ");
  438.     {
  439.         va_list va;
  440.         va_start(va, szFormat);
  441.         wvsprintf(ach+lstrlen(ach), szFormat, va);
  442.         va_end(va);
  443.     }
  444.     lstrcat(ach, "rn");
  445.     OutputDebugString(ach);
  446. }
  447. #endif