home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / misc / vfwdk / samples / icmapp / icm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-27  |  21.5 KB  |  649 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  ICM.C
  4. //
  5. //      helper routines for compressing/decompressing/and choosing compressors.
  6. //
  7. //      in order to use the ICChooseCompressor() function you need to include
  8. //      ICM.DLG into your apps resource file.
  9. //
  10. //      (C) Copyright Microsoft Corp. 1991, 1992, 1993.  All rights reserved.
  11. //
  12. //      You have a royalty-free right to use, modify, reproduce and
  13. //      distribute the Sample Files (and/or any modified version) in
  14. //      any way you find useful, provided that you agree that
  15. //      Microsoft has no warranty obligations or liability for any
  16. //      Sample Application Files.
  17. //
  18. //      If you did not get this from Microsoft Sources, then it may not be the
  19. //      most current version.  This sample code in particular will be updated
  20. //      and include more documentation.
  21. //
  22. //      Sources are:
  23. //         CompuServe: WINSDK forum, MDK section.
  24. //         Anonymous FTP from ftp.uu.net vendor\microsoft\multimedia
  25. //
  26. ///////////////////////////////////////////////////////////////////////////////
  27. #include <windows.h>
  28. #include <windowsx.h>
  29. #include <compman.h>
  30. #include "icm.h"
  31.  
  32. #include "icm.dlg"
  33.  
  34. // C6 needs this redefined.
  35. #undef GlobalFreePtr
  36. #define GlobalFreePtr(p)  (BOOL)GlobalFree(GlobalPtrHandle(p))
  37.  
  38. ///////////////////////////////////////////////////////////////////////////////
  39. //  DIB Macros
  40. ///////////////////////////////////////////////////////////////////////////////
  41.  
  42. #define WIDTHBYTES(i)           ((unsigned)((i+31)&(~31))/8)  /* ULONG aligned ! */
  43. #define DibWidthBytes(lpbi)     (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth * (UINT)((lpbi)->biBitCount))
  44.  
  45. #define DibSizeImage(lpbi)      ((DWORD)(UINT)DibWidthBytes(lpbi) * (DWORD)(UINT)((lpbi)->biHeight))
  46. #define DibSize(lpbi)           ((lpbi)->biSize + (lpbi)->biSizeImage + (int)(lpbi)->biClrUsed * sizeof(RGBQUAD))
  47.  
  48. #define DibPtr(lpbi)            (LPVOID)(DibColors(lpbi) + (UINT)(lpbi)->biClrUsed)
  49. #define DibColors(lpbi)         ((LPRGBQUAD)((LPBYTE)(lpbi) + (int)(lpbi)->biSize))
  50.  
  51. #define DibNumColors(lpbi)      ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
  52.                                     ? (int)(1 << (int)(lpbi)->biBitCount)          \
  53.                                     : (int)(lpbi)->biClrUsed)
  54.  
  55. ///////////////////////////////////////////////////////////////////////////////
  56. //
  57. //  ICCompressDecompressImage
  58. //
  59. //      compresses or decompresses a given image.
  60. //
  61. //  input:
  62. //      hic         compressor to use, if NULL is specifed a
  63. //                  compressor will be located that can handle the conversion.
  64. //      uiFlags     flags (not used, must be 0)
  65. //      lpbiIn      input DIB format
  66. //      lpBits      input DIB bits
  67. //      lpbiOut     output format, if NULL is specifed the default
  68. //                  format choosen be the compressor will be used.
  69. //      lQuality    the reqested compression quality
  70. //
  71. //  returns:
  72. //      a HANDLE to the converted image.  The handle is a DIB in CF_DIB
  73. //      format, ie a packed DIB.  The caller is responsible for freeing
  74. //      the memory.   NULL is returned if error.
  75. //
  76. ///////////////////////////////////////////////////////////////////////////////
  77. HANDLE FAR ICCompressDecompressImage(
  78.     HIC                     hic,        // compressor (NULL if any will do)
  79.     UINT                    uiFlags,    // silly flags
  80.     LPBITMAPINFOHEADER      lpbiIn,     // input DIB format
  81.     LPVOID                  lpBits,     // input DIB bits
  82.     LPBITMAPINFOHEADER      lpbiOut,    // output format (NULL => default)
  83.     LONG                    lQuality)   // the reqested quality
  84. {
  85.     HANDLE h;
  86.  
  87.     if (lpbiIn->biCompression == 0)
  88.         (h = ICCompressImage  (hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality)) ||
  89.         (h = ICDecompressImage(hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality)) ;
  90.     else
  91.         (h = ICDecompressImage(hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality)) ||
  92.         (h = ICCompressImage  (hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality)) ;
  93.  
  94.     return h;
  95. }
  96.  
  97. ///////////////////////////////////////////////////////////////////////////////
  98. //
  99. //  ICCompressImage
  100. //
  101. //      compresses a given image.
  102. //
  103. //  input:
  104. //      hic         compressor to use, if NULL is specifed a
  105. //                  compressor will be located that can handle the conversion.
  106. //      uiFlags     flags (not used, must be 0)
  107. //      lpbiIn      input DIB format
  108. //      lpBits      input DIB bits
  109. //      lpbiOut     output format, if NULL is specifed the default
  110. //                  format choosen be the compressor will be used.
  111. //      lQuality    the reqested compression quality
  112. //
  113. //  returns:
  114. //      a HANDLE to the converted image.  The handle is a DIB in CF_DIB
  115. //      format, ie a packed DIB.  The caller is responsible for freeing
  116. //      the memory.   NULL is returned if error.
  117. //
  118. ///////////////////////////////////////////////////////////////////////////////
  119. HANDLE FAR ICCompressImage(
  120.     HIC                     hic,        // compressor (NULL if any will do)
  121.     UINT                    uiFlags,    // silly flags
  122.     LPBITMAPINFOHEADER      lpbiIn,     // input DIB format
  123.     LPVOID                  lpBits,     // input DIB bits
  124.     LPBITMAPINFOHEADER      lpbiOut,    // output format (NULL => default)
  125.     LONG                    lQuality)   // the reqested quality
  126. {
  127.     LONG    l;
  128.     BOOL    fNuke;
  129.     DWORD   dwFlags = 0;
  130.     DWORD   ckid = 0;
  131.  
  132.     LPBITMAPINFOHEADER lpbi=NULL;
  133.  
  134.     //
  135.     // either locate a compressor or use the one supplied.
  136.     //
  137.     if (fNuke = (hic == NULL))
  138.     {
  139.         hic = ICLocate(ICTYPE_VIDEO, 0L, lpbiIn, lpbiOut, ICMODE_COMPRESS);
  140.  
  141.         if (hic == NULL)
  142.             return NULL;
  143.     }
  144.  
  145.     //
  146.     // make sure the found compressor can handle this format.
  147.     //
  148.     if (ICCompressQuery(hic, lpbiIn, NULL) != ICERR_OK)
  149.         goto error;
  150.  
  151.     //
  152.     //  now make a DIB header big enought to hold the ouput format
  153.     //
  154.     l = ICCompressGetFormatSize(hic, lpbiIn);
  155.  
  156.     if (l <= 0)
  157.         goto error;
  158.  
  159.     lpbi = (LPVOID)GlobalAllocPtr(GHND, l + 256*sizeof(RGBQUAD));
  160.  
  161.     if (lpbi == NULL)
  162.         goto error;
  163.  
  164.     //
  165.     //  if the compressor likes the passed format, use it else use the default
  166.     //  format of the compressor.
  167.     //
  168.     if (lpbiOut == NULL || ICCompressQuery(hic, lpbiIn, lpbiOut) != ICERR_OK)
  169.         ICCompressGetFormat(hic, lpbiIn, lpbi);
  170.     else
  171.         hmemcpy(lpbi, lpbiOut, lpbiOut->biSize + lpbiOut->biClrUsed * sizeof(RGBQUAD));
  172.  
  173.     lpbi->biSizeImage = ICCompressGetSize(hic, lpbiIn, lpbi);
  174.     lpbi->biClrUsed = DibNumColors(lpbi);
  175.  
  176.     //
  177.     // now resize the DIB to be the maximal size.
  178.     //
  179.     lpbi = (LPVOID)GlobalReAllocPtr(lpbi,DibSize(lpbi), 0);
  180.  
  181.     if (lpbi == NULL)
  182.         goto error;
  183.  
  184.     //
  185.     // now compress it.
  186.     //
  187.     if (ICCompressBegin(hic, lpbiIn, lpbi) != ICERR_OK)
  188.         goto error;
  189.  
  190.     if (lpBits == NULL)
  191.         lpBits = DibPtr(lpbiIn);
  192.  
  193.     if (lQuality == ICQUALITY_DEFAULT)
  194.         lQuality = ICGetDefaultQuality(hic);
  195.  
  196.     l = ICCompress(hic,
  197.             0,              // flags
  198.             lpbi,           // output format
  199.             DibPtr(lpbi),   // output data
  200.             lpbiIn,         // format of frame to compress
  201.             lpBits,         // frame data to compress
  202.             &ckid,          // ckid for data in AVI file
  203.             &dwFlags,       // flags in the AVI index.
  204.             0,              // frame number of seq.
  205.             0,              // reqested size in bytes. (if non zero)
  206.             lQuality,       // quality
  207.             NULL,           // format of previous frame
  208.             NULL);          // previous frame
  209.  
  210.     if (l < ICERR_OK)
  211.         goto error;
  212.  
  213.     if (ICCompressEnd(hic) != ICERR_OK)
  214.         goto error;
  215.  
  216.     //
  217.     // now resize the DIB to be the real size.
  218.     //
  219.     lpbi = (LPVOID)GlobalReAllocPtr(lpbi, DibSize(lpbi), 0);
  220.  
  221.     //
  222.     // all done return the result to the caller
  223.     //
  224.     if (fNuke)
  225.         ICClose(hic);
  226.  
  227.     return GlobalPtrHandle(lpbi);
  228.  
  229. error:
  230.     if (lpbi)
  231.         GlobalFreePtr(lpbi);
  232.  
  233.     if (fNuke)
  234.         ICClose(hic);
  235.  
  236.     return NULL;
  237. }
  238.  
  239. ///////////////////////////////////////////////////////////////////////////////
  240. //
  241. //  ICDecompressImage
  242. //
  243. //      decompresses a given image.
  244. //
  245. //  input:
  246. //      hic         compressor to use, if NULL is specifed a
  247. //                  compressor will be located that can handle the conversion.
  248. //      uiFlags     flags (not used, must be 0)
  249. //      lpbiIn      input DIB format
  250. //      lpBits      input DIB bits
  251. //      lpbiOut     output format, if NULL is specifed the default
  252. //                  format choosen be the compressor will be used.
  253. //      lQuality    the reqested compression quality
  254. //
  255. //  returns:
  256. //      a HANDLE to the converted image.  The handle is a DIB in CF_DIB
  257. //      format, ie a packed DIB.  The caller is responsible for freeing
  258. //      the memory.   NULL is returned if error.
  259. //
  260. ///////////////////////////////////////////////////////////////////////////////
  261. HANDLE FAR ICDecompressImage(
  262.     HIC                     hic,        // compressor (NULL if any will do)
  263.     UINT                    uiFlags,    // silly flags
  264.     LPBITMAPINFOHEADER      lpbiIn,     // input DIB format
  265.     LPVOID                  lpBits,     // input DIB bits
  266.     LPBITMAPINFOHEADER      lpbiOut,    // output format (NULL => default)
  267.     LONG                    lQuality)   // the reqested quality
  268. {
  269.     LONG    l;
  270.     BOOL    fNuke;
  271.     DWORD   dwFlags = 0;
  272.     DWORD   ckid = 0;
  273.  
  274.     LPBITMAPINFOHEADER lpbi=NULL;
  275.  
  276.     //
  277.     // either locate a compressor or use the one supplied.
  278.     //
  279.     if (fNuke = (hic == NULL))
  280.     {
  281.         hic = ICLocate(ICTYPE_VIDEO, 0L, lpbiIn, lpbiOut, ICMODE_DECOMPRESS);
  282.  
  283.         if (hic == NULL)
  284.             return NULL;
  285.     }
  286.  
  287.     //
  288.     // make sure the found compressor can handle this format.
  289.     //
  290.     if (ICDecompressQuery(hic, lpbiIn, NULL) != ICERR_OK)
  291.         goto error;
  292.  
  293.     //
  294.     //  make a DIB header big enought to hold the ouput format
  295.     //
  296.     l = ICDecompressGetFormatSize(hic, lpbiIn);
  297.  
  298.     if (l <= 0)
  299.         goto error;
  300.  
  301.     lpbi = (LPVOID)GlobalAllocPtr(GHND, l + 256*sizeof(RGBQUAD));
  302.  
  303.     if (lpbi == NULL)
  304.         goto error;
  305.  
  306.     //
  307.     //  if the compressor likes the passed format, use it else use the default
  308.     //  format of the compressor.
  309.     //
  310.     if (lpbiOut == NULL || ICDecompressQuery(hic, lpbiIn, lpbiOut) != ICERR_OK)
  311.         ICDecompressGetFormat(hic, lpbiIn, lpbi);
  312.     else
  313.         hmemcpy(lpbi, lpbiOut, lpbiOut->biSize + lpbiOut->biClrUsed * sizeof(RGBQUAD));
  314.  
  315.     //
  316.     // for decompress make sure the palette (ie color table) is correct
  317.     //
  318.     if (lpbi->biBitCount <= 8)
  319.         ICDecompressGetPalette(hic, lpbiIn, lpbi);
  320.  
  321.     lpbi->biSizeImage = DibSizeImage(lpbi); // ICDecompressGetSize(hic, lpbi);
  322.     lpbi->biClrUsed = DibNumColors(lpbi);
  323.  
  324.     //
  325.     // now resize the DIB to be the right size.
  326.     //
  327.     lpbi = (LPVOID)GlobalReAllocPtr(lpbi,DibSize(lpbi),0);
  328.  
  329.     if (lpbi == NULL)
  330.         goto error;
  331.  
  332.     //
  333.     // now decompress it.
  334.     //
  335.     if (ICDecompressBegin(hic, lpbiIn, lpbi) != ICERR_OK)
  336.         goto error;
  337.  
  338.     if (lpBits == NULL)
  339.         lpBits = DibPtr(lpbiIn);
  340.  
  341.     l = ICDecompress(hic,
  342.             0,              // flags
  343.             lpbiIn,         // format of frame to decompress
  344.             lpBits,         // frame data to decompress
  345.             lpbi,           // output format
  346.             DibPtr(lpbi));  // output data
  347.  
  348.     if (l < ICERR_OK)
  349.         goto error;
  350.  
  351.     if (ICDecompressEnd(hic) != ICERR_OK)
  352.         goto error;
  353.  
  354.     //
  355.     // now resize the DIB to be the real size.
  356.     //
  357.     lpbi = (LPVOID)GlobalReAllocPtr(lpbi,DibSize(lpbi),0);
  358.  
  359.     //
  360.     // all done return the result to the caller
  361.     //
  362.     if (fNuke)
  363.         ICClose(hic);
  364.  
  365.     return GlobalPtrHandle(lpbi);
  366.  
  367. error:
  368.     if (lpbi)
  369.         GlobalFreePtr(lpbi);
  370.  
  371.     if (fNuke)
  372.         ICClose(hic);
  373.  
  374.     return NULL;
  375. }
  376.  
  377.  
  378. ///////////////////////////////////////////////////////////////////////////////
  379. //
  380. //  ICChooseCompressorStuff
  381. //
  382. ///////////////////////////////////////////////////////////////////////////////
  383.  
  384. static BOOL CALLBACK ICChooseCompressorDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  385.  
  386. typedef struct {
  387.     DWORD       fccType;
  388.     UINT        uiFlags;
  389.     LPVOID      pvIn;
  390.     LPVOID      lpData;
  391.     HIC         hic;
  392.     LONG        lQuality;
  393.     ICINFO      icinfo;
  394. } ICChooseCompressorStuff, FAR *PICChooseCompressorStuff;
  395.  
  396. ///////////////////////////////////////////////////////////////////////////////
  397. //
  398. //  ICChooseCompressor
  399. //
  400. //      Brings up a dialog and allows the user to choose a compression
  401. //      method and a quality level.  all compressors in the system are
  402. //      displayed and are optionaly filtered by "ability to compress" a
  403. //      specifed format.
  404. //
  405. //      the dialog allows the user to configure or bring up the compressors
  406. //      about box.
  407. //
  408. //      the selected compressor is opened (via ICOpen) and returned to the
  409. //      caller, it must be disposed of with ICClose() when no longer in use.
  410. //
  411. //  input:
  412. //      HWND    hwnd            parent window for dialog box.
  413. //      DWORD   fccType         compressor types to display. use ICTYPE_VIDEO for video compressors.
  414. //      UINT    uiFlags         flags, unused must be 0
  415. //      LPVOID  pvIn            input format (optional), only compressors that handle this format will be displayed.
  416. //      LPVOID  lpData          input data (optional, currently not used) is specifed this data will be used as a compress preview.
  417. //      HIC     FAR *phic       return HIC (caller must call ICClose when done)
  418. //      LONG    FAR *plQuality  return quality
  419. //
  420. //  returns:
  421. //      TRUE if dialog shown and user choosed a compressor.
  422. //      FALSE if dialog was not shown or user hit cancel.
  423. //
  424. ///////////////////////////////////////////////////////////////////////////////
  425.  
  426. BOOL FAR ICChooseCompressor(
  427.     HWND        hwnd,               // parent window for dialog
  428.     DWORD       fccType,            // compressor type to choose
  429.     UINT        uiFlags,            // flags.
  430.     LPVOID      pvIn,               // input format (optional)
  431.     LPVOID      lpData,             // input data (optional)
  432.     HIC         FAR *phic,          // return HIC (caller must free)
  433.     LONG        FAR *plQuality)     // return quality
  434. {
  435.     BOOL f;
  436.     PICChooseCompressorStuff p;
  437.  
  438.     if (fccType == 0)
  439.         fccType = ICTYPE_VIDEO;
  440.  
  441.     p = (LPVOID)GlobalAllocPtr(GHND, sizeof(ICChooseCompressorStuff));
  442.  
  443.     if (p == NULL)
  444.         return FALSE;
  445.  
  446.     p->fccType   = fccType;
  447.     p->uiFlags   = uiFlags;
  448.     p->pvIn      = pvIn;
  449.     p->lQuality  = plQuality ? *plQuality : ICQUALITY_DEFAULT;
  450.  
  451.     f = DialogBoxParam(GetWindowInstance(hwnd),
  452.         "ICChooseCompressor", hwnd, ICChooseCompressorDlgProc, (LPARAM)(LPVOID)p);
  453.  
  454.     //
  455.     // if the user picked a compressor then return this info to the caller
  456.     //
  457.     if (f)
  458.     {
  459.         if (plQuality)
  460.             *plQuality = p->lQuality;
  461.  
  462.         if (phic)
  463.             *phic = p->hic;
  464.         else if (p->hic)
  465.             ICClose(p->hic);
  466.     }
  467.  
  468.     GlobalFreePtr(p);
  469.  
  470.     return f;
  471. }
  472.  
  473. ///////////////////////////////////////////////////////////////////////////////
  474. //
  475. //  ICChooseCompressorDlgProc
  476. //
  477. //  dialog box procedure for ICChooseCompressor, a pointer to a
  478. //  ICChooseCompressorStuff pointer must be passed to initialize this
  479. //  dialog.
  480. //
  481. //  NOTE: this dialog box procedure does not use any globals
  482. //  so I did not bother to _export it or use MakeProcAddress() if
  483. //  you change this code to use globals, etc, be aware of this fact.
  484. //
  485. ///////////////////////////////////////////////////////////////////////////////
  486.  
  487. static BOOL CALLBACK ICChooseCompressorDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  488. {
  489.     int i,n;
  490.     int pos;
  491.     HWND hwndC;
  492.     PICChooseCompressorStuff p;
  493.     HIC hic;
  494.     BOOL fConfig, fAbout, fQuality;
  495.  
  496.     p = (PICChooseCompressorStuff)GetWindowLong(hwnd,DWL_USER);
  497.  
  498.     switch (msg)
  499.     {
  500.         case WM_INITDIALOG:
  501.             if (lParam == NULL)
  502.                 return FALSE;
  503.  
  504.             SetWindowLong(hwnd,DWL_USER,lParam);
  505.             p = (PICChooseCompressorStuff)lParam;
  506.  
  507.             //
  508.             // now fill the combo box with all compressors
  509.             //
  510.             hwndC = GetDlgItem(hwnd, ID_COMPRESSOR);
  511.  
  512.             for (i=0; ICInfo(p->fccType, i, &p->icinfo); i++)
  513.             {
  514.                 hic = ICOpen(p->icinfo.fccType, p->icinfo.fccHandler, ICMODE_QUERY);
  515.  
  516.                 if (hic)
  517.                 {
  518.                     //
  519.                     // skip this compressor if it can't handle the
  520.                     // specifed format
  521.                     //
  522.                     if (p->fccType == ICTYPE_VIDEO &&
  523.                         p->pvIn != NULL &&
  524.                         ICCompressQuery(hic, p->pvIn, NULL) != ICERR_OK &&
  525.                         ICDecompressQuery(hic, p->pvIn, NULL) != ICERR_OK)
  526.                     {
  527.                         ICClose(hic);
  528.                         continue;
  529.                     }
  530.  
  531.                     //
  532.                     // find out the compressor name.
  533.                     //
  534.                     ICGetInfo(hic, &p->icinfo, sizeof(p->icinfo));
  535.  
  536.                     //
  537.                     // stuff it into the combo box
  538.                     //
  539.                     n = ComboBox_AddString(hwndC,p->icinfo.szDescription);
  540.                     ComboBox_SetItemData(hwndC, n, hic);
  541.                 }
  542.             }
  543.  
  544.             SetScrollRange(GetDlgItem(hwnd, ID_QUALITY),SB_CTL,0,100,TRUE);
  545.             ComboBox_SetCurSel(hwndC, 0);
  546.             PostMessage(hwnd, WM_COMMAND, ID_COMPRESSOR, MAKELONG(hwndC, CBN_SELCHANGE));
  547.             return TRUE;
  548.  
  549.         case WM_HSCROLL:
  550.             pos = GetScrollPos((HWND)HIWORD(lParam),SB_CTL);
  551.  
  552.             switch (wParam)
  553.             {
  554.                 case SB_LINEDOWN:      pos += 1; break;
  555.                 case SB_LINEUP:        pos -= 1; break;
  556.                 case SB_PAGEDOWN:      pos += 10; break;
  557.                 case SB_PAGEUP:        pos -= 10; break;
  558.                 case SB_THUMBTRACK:
  559.                 case SB_THUMBPOSITION: pos = LOWORD(lParam); break;
  560.                 default:
  561.                     return TRUE;
  562.             }
  563.  
  564.             if (pos < 0)
  565.                 pos = 0;
  566.             if (pos > (ICQUALITY_HIGH/100))
  567.                 pos = (ICQUALITY_HIGH/100);
  568.  
  569.             SetDlgItemInt(hwnd, ID_QUALITYTEXT, pos, FALSE);
  570.             SetScrollPos((HWND)HIWORD(lParam), SB_CTL, pos, TRUE);
  571.             break;
  572.  
  573.         case WM_COMMAND:
  574.             hwndC = GetDlgItem(hwnd, ID_COMPRESSOR);
  575.             n = ComboBox_GetCurSel(hwndC);
  576.             hic = n == -1 ? NULL : (HIC)ComboBox_GetItemData(hwndC,n);
  577.  
  578.             switch ((int)wParam)
  579.             {
  580.                 case ID_COMPRESSOR:
  581.                     if (HIWORD(lParam) != CBN_SELCHANGE)
  582.                         break;
  583.  
  584.                     if (hic)
  585.                     {
  586.                         ICGetInfo(hic, &p->icinfo, sizeof(p->icinfo));
  587.  
  588.                         fConfig  = ICQueryConfigure(hic);
  589.                         fAbout   = ICQueryAbout(hic);
  590.                         fQuality = (p->icinfo.dwFlags & VIDCF_QUALITY) != 0;
  591.  
  592.                         EnableWindow(GetDlgItem(hwnd, ID_CONFIG), fConfig);
  593.                         EnableWindow(GetDlgItem(hwnd, ID_ABOUT), fAbout);
  594.                         EnableWindow(GetDlgItem(hwnd, ID_QUALITY), fQuality);
  595.                         EnableWindow(GetDlgItem(hwnd, ID_QUALITYLABEL), fQuality);
  596.  
  597.                         if (fQuality)
  598.                         {
  599.                             if (p->lQuality == ICQUALITY_DEFAULT)
  600.                             {
  601.                                 SetScrollPos(GetDlgItem(hwnd, ID_QUALITY), SB_CTL,
  602.                                     (int)ICGetDefaultQuality(hic)/100, TRUE);
  603.                             }
  604.                             else
  605.                             {
  606.                                 SetScrollPos(GetDlgItem(hwnd, ID_QUALITY), SB_CTL,
  607.                                     (int)p->lQuality/100, TRUE);
  608.                             }
  609.  
  610.                             pos = GetScrollPos(GetDlgItem(hwnd, ID_QUALITY),SB_CTL);
  611.                             SetDlgItemInt(hwnd, ID_QUALITYTEXT, pos, FALSE);
  612.                         }
  613.                     }
  614.                     break;
  615.  
  616.                 case ID_CONFIG:
  617.                     if (hic)
  618.                         ICConfigure(hic, hwnd);
  619.                     break;
  620.  
  621.                 case ID_ABOUT:
  622.                     if (hic)
  623.                         ICAbout(hic, hwnd);
  624.                     break;
  625.  
  626.                 case IDOK:
  627.                     ComboBox_SetItemData(hwndC,n,0);
  628.  
  629.                     p->hic = hic;
  630.                     p->lQuality = 100 * GetScrollPos(GetDlgItem(hwnd, ID_QUALITY), SB_CTL);
  631.  
  632.                     // fall though
  633.  
  634.                 case IDCANCEL:
  635.                     n = ComboBox_GetCount(hwndC);
  636.                     for (i=0; i<n; i++)
  637.                     {
  638.                         if (hic = (HIC)ComboBox_GetItemData(hwndC,i))
  639.                             ICClose(hic);
  640.                     }
  641.                     EndDialog(hwnd, wParam == IDOK);
  642.                     break;
  643.             }
  644.             break;
  645.     }
  646.  
  647.     return FALSE;
  648. }
  649.