home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / video / vidcap / vidframe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  13.8 KB  |  556 lines

  1. /**************************************************************************
  2.  *
  3.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6.  *  PURPOSE.
  7.  *
  8.  *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  9.  *
  10.  **************************************************************************/
  11. /****************************************************************************
  12.  *
  13.  *   vidframe.c: Frame for the capture window
  14.  *
  15.  *   Vidcap32 Source code
  16.  *
  17.  ***************************************************************************/
  18.  
  19. /*
  20.  * Window class that provides a frame for the AVICAP window in the
  21.  * VidCap capture tool. Responsible for positioning within the
  22.  * parent window, handling scrolling and painting a size border if
  23.  * there is room.
  24.  */
  25.  
  26. #include <windows.h>
  27. #include <windowsx.h>
  28. #include <mmsystem.h>
  29. #include <mmreg.h>
  30. #include <vfw.h>
  31. #include "vidcap.h"
  32.  
  33. #include "vidframe.h"
  34.  
  35. /*
  36.  * pixels to move when asked to scroll one line or page
  37.  */
  38. #define LINE_SCROLL    10
  39. #define PAGE_SCROLL    50
  40.  
  41. // class name
  42. #define VIDFRAMECLASSNAME   "vidframeClass"
  43.  
  44.  
  45. /*
  46.  * standard brushes
  47.  */
  48. static HBRUSH ghbrBackground = NULL, ghbrFace, ghbrHighlight, ghbrShadow;
  49. static BOOL   fhbrBackgroundIsSysObj;
  50.  
  51.  
  52. /*
  53.  * create brushes to be used in painting
  54.  */
  55. void
  56. vidframeCreateTools(HWND hwnd)
  57. {
  58.  
  59.     vidframeSetBrush(hwnd, gBackColour);
  60.  
  61.     ghbrHighlight  = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
  62.     ghbrShadow  = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
  63.     ghbrFace  = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  64. }
  65.  
  66. void
  67. vidframeDeleteTools(void)
  68. {
  69.     if (ghbrBackground) {
  70.         if (!fhbrBackgroundIsSysObj) {
  71.             DeleteObject(ghbrBackground);
  72.             ghbrBackground = NULL;
  73.         }
  74.     }
  75.  
  76.     if (ghbrHighlight) {
  77.         DeleteObject(ghbrHighlight);
  78.         ghbrHighlight = NULL;
  79.     }
  80.  
  81.     if (ghbrShadow) {
  82.         DeleteObject(ghbrShadow);
  83.         ghbrShadow = NULL;
  84.     }
  85.  
  86.     if (ghbrFace) {
  87.         DeleteObject(ghbrFace);
  88.         ghbrFace = NULL;
  89.     }
  90. }
  91.  
  92.  
  93. /*
  94.  * change the background fill brush to be one of-
  95.  *  IDD_PrefsDefBackground  - windows default background colour
  96.  *  IDD_PrefsLtGrey - light grey
  97.  *  IDD_PrefsDkGrey - dark grey
  98.  *  IDD_PrefsBlack - black
  99.  */
  100. void
  101. vidframeSetBrush(HWND hwnd, int iPref)
  102. {
  103.     if (ghbrBackground != NULL) {
  104.         if (!fhbrBackgroundIsSysObj) {
  105.             DeleteObject(ghbrBackground);
  106.             ghbrBackground = NULL;
  107.         }
  108.     }
  109.  
  110.     switch(iPref) {
  111.     case IDD_PrefsDefBackground:
  112.         ghbrBackground = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  113.         fhbrBackgroundIsSysObj = FALSE;
  114.         break;
  115.  
  116.     case IDD_PrefsLtGrey:
  117.         ghbrBackground = GetStockObject(LTGRAY_BRUSH);
  118.         fhbrBackgroundIsSysObj = TRUE;
  119.         break;
  120.  
  121.     case IDD_PrefsDkGrey:
  122.         ghbrBackground = GetStockObject(DKGRAY_BRUSH);
  123.         fhbrBackgroundIsSysObj = TRUE;
  124.         break;
  125.  
  126.     case IDD_PrefsBlack:
  127.         ghbrBackground = GetStockObject(BLACK_BRUSH);
  128.         fhbrBackgroundIsSysObj = TRUE;
  129.         break;
  130.  
  131.     default:
  132.         return;
  133.     }
  134.  
  135.     if (hwnd != NULL) {
  136. #ifdef _WIN32
  137.         SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG) ghbrBackground);
  138. #else
  139.         SetClassWord(hwnd, GCW_HBRBACKGROUND, (WORD) ghbrBackground);
  140. #endif
  141.         InvalidateRect(hwnd, NULL, TRUE);
  142.     }
  143. }
  144.  
  145.  
  146.  
  147.  
  148. /*
  149.  * layout the window  - decide if we need scrollbars or
  150.  * not, and position the avicap window correctly
  151.  */
  152. void
  153. vidframeLayout(HWND hwnd, HWND hwndCap)
  154. {
  155.     RECT rc;
  156.     RECT rcCap;
  157.     CAPSTATUS cs;
  158.     int cx, cy;
  159.     POINT ptScroll;
  160.  
  161.  
  162.     // get the x and y scroll pos so we can reset them
  163.     ptScroll.y = GetScrollPos(hwnd, SB_VERT);
  164.     ptScroll.x = GetScrollPos(hwnd, SB_HORZ);
  165.  
  166.     GetClientRect(hwnd, &rc);
  167.     if (!capGetStatus(hwndCap, &cs, sizeof(cs))) {
  168.         // no current window? - make it 0 size
  169.         cs.uiImageWidth = 0;
  170.         cs.uiImageHeight = 0;
  171.  
  172.     }
  173.  
  174.     SetRect(&rcCap, 0, 0, cs.uiImageWidth, cs.uiImageHeight);
  175.  
  176.     /*
  177.      * check which scrollbars we need - note that adding and removing
  178.      * scrollbars affects the other dimension - so recheck client rect
  179.      */
  180.     if (RECTWIDTH(rcCap) < RECTWIDTH(rc)) {
  181.         // fits horz.
  182.         SetScrollRange(hwnd, SB_HORZ, 0, 0, TRUE);
  183.     } else {
  184.         // need horz scrollbar
  185.         SetScrollRange(hwnd, SB_HORZ, 0, RECTWIDTH(rcCap) - RECTWIDTH(rc), FALSE);
  186.     }
  187.  
  188.     // get client size in case shrunk/expanded
  189.     GetClientRect(hwnd, &rc);
  190.  
  191.     // check vert scrollbar
  192.     if (RECTHEIGHT(rcCap) < RECTHEIGHT(rc)) {
  193.         SetScrollRange(hwnd, SB_VERT, 0, 0, TRUE);
  194.     } else {
  195.         SetScrollRange(hwnd, SB_VERT, 0, RECTHEIGHT(rcCap) - RECTHEIGHT(rc), FALSE);
  196.  
  197.         // this may have caused the horz scrollbar to be unneeded
  198.         GetClientRect(hwnd, &rc);
  199.         if (RECTWIDTH(rcCap) < RECTWIDTH(rc)) {
  200.             // fits horz.
  201.             SetScrollRange(hwnd, SB_HORZ, 0, 0, TRUE);
  202.         } else {
  203.             // need horz scrollbar
  204.             SetScrollRange(hwnd, SB_HORZ, 0, RECTWIDTH(rcCap) - RECTWIDTH(rc), FALSE);
  205.         }
  206.     }
  207.  
  208.     /*
  209.      * be sure we don't leave any underwear showing if we have scrolled
  210.      * back or removed the scrollbars
  211.      */
  212.     {
  213.         int cmax, cmin;
  214.  
  215.         GetScrollRange(hwnd, SB_HORZ, &cmin, &cmax);
  216.         if (ptScroll.x > cmax) {
  217.             ptScroll.x = cmax;
  218.         }
  219.         GetScrollRange(hwnd, SB_VERT, &cmin, &cmax);
  220.         if (ptScroll.y > cmax) {
  221.             ptScroll.y = cmax;
  222.         }
  223.         SetScrollPos(hwnd, SB_HORZ, ptScroll.x, TRUE);
  224.         SetScrollPos(hwnd, SB_VERT, ptScroll.y, TRUE);
  225.         capSetScrollPos(hwndCap, &ptScroll);
  226.     }
  227.  
  228.     // centre the window if requested and if room
  229.     if(gbCentre) {
  230.         GetClientRect(hwnd, &rc);
  231.         cx = max(0, (RECTWIDTH(rc) - (int) cs.uiImageWidth)/2);
  232.         cy = max(0, (RECTHEIGHT(rc) - (int) cs.uiImageHeight)/2);
  233.         OffsetRect(&rcCap, cx, cy);
  234.     }
  235.  
  236.     // DWORD align the capture window for optimal codec speed
  237.     // during preview.  
  238.     rc = rcCap;
  239.     MapWindowPoints (hwnd, NULL, (LPPOINT)&rc, 1);
  240.     cx = rc.left - (rc.left & ~3);
  241.     OffsetRect(&rcCap, -cx, 0);
  242.  
  243.     MoveWindow(hwndCap,
  244.             rcCap.left, rcCap.top,         
  245.             RECTWIDTH(rcCap), RECTHEIGHT(rcCap),
  246.             TRUE);
  247.  
  248.     InvalidateRect(hwnd, NULL, TRUE);
  249. }
  250.  
  251. /*
  252.  * paint the vidframe window. The fill colour is always selected as the
  253.  * background brush, so all we need to do here is paint the
  254.  * fancy border around the inner window if room.
  255.  */
  256. void
  257. vidframePaint(HWND hwnd, HWND hwndCap)
  258. {
  259.     POINT ptInner;
  260.     RECT rcCap;
  261.     PAINTSTRUCT ps;
  262.     HDC hdc;
  263.     HBRUSH hbr;
  264.     int cx, cy;
  265.  
  266.     hdc = BeginPaint(hwnd, &ps);
  267.  
  268.     /*
  269.      * first calculate the location of the upper left corner
  270.      * of the avicap window in vidframe-window client co-ordinates
  271.      */
  272.     ptInner.x = 0;
  273.     ptInner.y = 0;
  274.     MapWindowPoints(hwndCap, hwnd, &ptInner, 1);
  275.  
  276.     // width and height of cap window
  277.     GetWindowRect(hwndCap, &rcCap);
  278.     cx = RECTWIDTH(rcCap);
  279.     cy = RECTHEIGHT(rcCap);
  280.  
  281.     // shadow lines
  282.     hbr = SelectObject(hdc, ghbrShadow);
  283.     PatBlt(hdc, ptInner.x-1, ptInner.y-1, cx + 1, 1, PATCOPY);
  284.     PatBlt(hdc, ptInner.x-1, ptInner.y-1, 1, cy + 1, PATCOPY);
  285.     PatBlt(hdc, ptInner.x + cx + 4, ptInner.y-5, 1, cy+10, PATCOPY);
  286.     PatBlt(hdc, ptInner.x -5, ptInner.y+cy+4, cx+10, 1, PATCOPY);
  287.  
  288.     // hi-light lines
  289.     SelectObject(hdc, ghbrHighlight);
  290.     PatBlt(hdc, ptInner.x - 5, ptInner.y - 5, 1, cy+9, PATCOPY);
  291.     PatBlt(hdc, ptInner.x - 5, ptInner.y - 5, cx+9, 1, PATCOPY);
  292.     PatBlt(hdc, ptInner.x+cx, ptInner.y-1, 1, cy+2, PATCOPY);
  293.     PatBlt(hdc, ptInner.x-1, ptInner.y+cy, cx, 1, PATCOPY);
  294.  
  295.     // fill bordered area with button face colour
  296.     SelectObject(hdc, ghbrFace);
  297.     PatBlt(hdc, ptInner.x-4, ptInner.y-4, cx+8, 3, PATCOPY);
  298.     PatBlt(hdc, ptInner.x-4, ptInner.y+cy+1, cx+8, 3, PATCOPY);
  299.     PatBlt(hdc, ptInner.x-4, ptInner.y-1, 3, cy+2, PATCOPY);
  300.     PatBlt(hdc, ptInner.x+cx+1, ptInner.y-1, 3, cy+2, PATCOPY);
  301.  
  302.     SelectObject(hdc, hbr);
  303.  
  304.     EndPaint(hwnd, &ps);
  305.  
  306. }
  307.  
  308. /*
  309.  * respond to a scrollbar message by moving the current scroll
  310.  * position horizontally
  311.  */
  312. void
  313. vidframeHScroll(HWND hwnd, HWND hwndCap, int code, int pos)
  314. {
  315.     POINT pt;
  316.     int cmax, cmin;
  317.  
  318.     pt.x = GetScrollPos(hwnd, SB_HORZ);
  319.     pt.y = GetScrollPos(hwnd, SB_VERT);
  320.     GetScrollRange(hwnd, SB_HORZ, &cmin, &cmax);
  321.  
  322.  
  323.     switch(code) {
  324.     case SB_LINEUP:
  325.         pt.x -= LINE_SCROLL;
  326.         break;
  327.  
  328.     case SB_LINEDOWN:
  329.         pt.x += LINE_SCROLL;
  330.         break;
  331.  
  332.     case SB_PAGEUP:
  333.         pt.x -= PAGE_SCROLL;
  334.         break;
  335.  
  336.     case SB_PAGEDOWN:
  337.         pt.x += PAGE_SCROLL;
  338.         break;
  339.  
  340.     case SB_THUMBTRACK:
  341.     case SB_THUMBPOSITION:
  342.         pt.x = pos;
  343.         break;
  344.     }
  345.  
  346.     if (pt.x < cmin) {
  347.         pt.x = cmin;
  348.     } else if (pt.x > cmax) {
  349.         pt.x = cmax;
  350.     }
  351.     SetScrollPos(hwnd, SB_HORZ, pt.x, TRUE);
  352.     capSetScrollPos(hwndCap, &pt);
  353.  
  354. }
  355.  
  356.  
  357. /*
  358.  * respond to a scrollbar message by moving the current scroll
  359.  * position vertically
  360.  */
  361. void
  362. vidframeVScroll(HWND hwnd, HWND hwndCap, int code, int pos)
  363. {
  364.     POINT pt;
  365.     int cmax, cmin;
  366.  
  367.     pt.x = GetScrollPos(hwnd, SB_HORZ);
  368.     pt.y = GetScrollPos(hwnd, SB_VERT);
  369.     GetScrollRange(hwnd, SB_VERT, &cmin, &cmax);
  370.  
  371.  
  372.     switch(code) {
  373.     case SB_LINEUP:
  374.         pt.y -= LINE_SCROLL;
  375.         break;
  376.  
  377.     case SB_LINEDOWN:
  378.         pt.y += LINE_SCROLL;
  379.         break;
  380.  
  381.     case SB_PAGEUP:
  382.         pt.y -= PAGE_SCROLL;
  383.         break;
  384.  
  385.     case SB_PAGEDOWN:
  386.         pt.y += PAGE_SCROLL;
  387.         break;
  388.  
  389.     case SB_THUMBTRACK:
  390.     case SB_THUMBPOSITION:
  391.         pt.y = pos;
  392.         break;
  393.     }
  394.  
  395.     if (pt.y < cmin) {
  396.         pt.y = cmin;
  397.     } else if (pt.y > cmax) {
  398.         pt.y = cmax;
  399.     }
  400.     SetScrollPos(hwnd, SB_VERT, pt.y, TRUE);
  401.     capSetScrollPos(hwndCap, &pt);
  402. }
  403.  
  404.  
  405.  
  406. LONG FAR PASCAL 
  407. vidframeProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  408. {
  409.  
  410.     switch(message) {
  411.  
  412.     case WM_MOVE:
  413.     case WM_SIZE:
  414.         if (ghWndCap) {
  415.             vidframeLayout(hwnd, ghWndCap);
  416.         }
  417.         break;
  418.  
  419.     case WM_SYSCOLORCHANGE:
  420.         // re-get brushes - we will be sent a paint message
  421.         vidframeDeleteTools();
  422.         vidframeCreateTools(hwnd);
  423.         return(TRUE);
  424.  
  425.  
  426.     case WM_PALETTECHANGED:
  427.     case WM_QUERYNEWPALETTE:
  428.         // allow the avicap window to handle this
  429.         if (ghWndCap) {
  430.             return SendMessage(ghWndCap, message, wParam, lParam) ;
  431.         }
  432.  
  433.     case WM_PAINT:
  434.         if (ghWndCap) {
  435.             vidframePaint(hwnd, ghWndCap);
  436.         }
  437.         break;
  438.  
  439.     case WM_HSCROLL:
  440.         if (ghWndCap) {
  441.             vidframeHScroll(hwnd, ghWndCap,
  442.                 GET_WM_HSCROLL_CODE(wParam, lParam),
  443.                 GET_WM_HSCROLL_POS(wParam, lParam)
  444.                 );
  445.         }
  446.         break;
  447.  
  448.     case WM_VSCROLL:
  449.         if (ghWndCap) {
  450.             vidframeVScroll(hwnd, ghWndCap,
  451.                 GET_WM_VSCROLL_CODE(wParam, lParam),
  452.                 GET_WM_VSCROLL_POS(wParam, lParam)
  453.                 );
  454.         }
  455.         break;
  456.  
  457.     case WM_DESTROY:
  458.         vidframeDeleteTools();
  459.         break;
  460.  
  461.     default:
  462.         return(DefWindowProc(hwnd, message, wParam, lParam));
  463.  
  464.     }
  465.     return(0);
  466. }
  467.  
  468.  
  469.  
  470. /*
  471.  * create a frame window and child capture window at the
  472.  * given location. Initialise the class if this is the
  473.  * first time through.
  474.  *
  475.  * returns the window handle of the frame window
  476.  * (or NULL if failure). returns the window handle of the AVICAP window
  477.  * via phwndCap.
  478.  */
  479. HWND
  480. vidframeCreate(
  481.     HWND hwndParent,
  482.     HINSTANCE hInstance,
  483.     HINSTANCE hPrevInstance,
  484.     int x,
  485.     int y,
  486.     int cx,
  487.     int cy,
  488.     HWND FAR * phwndCap
  489. )
  490. {
  491.     HWND hwnd, hwndCap;
  492.     static BOOL bInitDone = FALSE;
  493.  
  494.     if (!bInitDone) {
  495.         WNDCLASS wc;
  496.  
  497.         vidframeCreateTools(NULL);
  498.  
  499.         if (!hPrevInstance) {
  500.             // If it's the first instance, register the window class
  501.             wc.lpszClassName = VIDFRAMECLASSNAME;
  502.             wc.hInstance     = hInstance;
  503.             wc.lpfnWndProc   = vidframeProc;
  504.             wc.hCursor       = LoadCursor(NULL, IDC_ARROW) ;
  505.             wc.hIcon         = NULL;
  506.             wc.lpszMenuName  = NULL;
  507.             wc.hbrBackground = ghbrBackground;
  508.             wc.style         = CS_HREDRAW | CS_VREDRAW ;
  509.             wc.cbClsExtra    = 0 ;
  510.             wc.cbWndExtra    = 0 ;   
  511.  
  512.             if(!RegisterClass(&wc)) {
  513.                 return(NULL);
  514.             }
  515.         }
  516.         bInitDone = TRUE;
  517.     }
  518.  
  519.     hwnd = CreateWindowEx(
  520.                 gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0,
  521.                 VIDFRAMECLASSNAME,
  522.                 NULL,
  523.                 WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|WS_CLIPCHILDREN,
  524.                 x, y, cx, cy,
  525.                 hwndParent,
  526.                 (HMENU) 0,
  527.                 hInstance,
  528.                 NULL);
  529.  
  530.     if (hwnd == NULL) {
  531.         return(NULL);
  532.     }
  533.  
  534.  
  535.     /*
  536.      * create an AVICAP window within this window. Leave vidframeLayout
  537.      * to do the layout
  538.      */
  539.     hwndCap = capCreateCaptureWindow(
  540.                     NULL,
  541.                     WS_CHILD | WS_VISIBLE,
  542.                     0, 0, 160, 120,
  543.                     hwnd,               // parent window
  544.                     1                   // child window id
  545.               );
  546.  
  547.  
  548.     if (hwndCap == NULL) {
  549.         return(NULL);
  550.     }
  551.  
  552.     *phwndCap = hwndCap;
  553.     return(hwnd);
  554. }
  555.  
  556.