Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2362 lines
70 KiB

  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 - 1995 Microsoft Corporation. All Rights Reserved.
  9. *
  10. **************************************************************************/
  11. /****************************************************************************
  12. *
  13. * vidcap.c: WinMain and command processing
  14. *
  15. * Vidcap32 Source code
  16. *
  17. ***************************************************************************/
  18. #include <windows.h>
  19. #include <windowsx.h>
  20. #include <commdlg.h>
  21. #include <mmsystem.h>
  22. #include <mmreg.h>
  23. #include <io.h>
  24. #include <fcntl.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <memory.h>
  28. #include <dos.h>
  29. #include <shellapi.h>
  30. #include <vfw.h>
  31. #include <tchar.h>
  32. #include "vidcap.h"
  33. #include "vidframe.h"
  34. #include "profile.h"
  35. // generic window control classes
  36. #include "toolbar.h"
  37. #include "status.h"
  38. #include "arrow.h"
  39. #include "rlmeter.h"
  40. #include "help.h"
  41. // the standard toolbar class 'exports' this but doesn't put it in the
  42. // header file
  43. extern TCHAR szToolBarClass[];//HACK!
  44. // height of the buttons on a toolbar - depends on the
  45. // size of the bitmaps within IDBMP_TOOLBAR
  46. #define BUTTONWIDTH 24
  47. #define BUTTONHEIGHT 22
  48. #define TOOLBAR_HEIGHT BUTTONHEIGHT + 6
  49. // description and layout of toolbar buttons within IDBMP_TOOLBAR
  50. #define APP_NUMTOOLS 8
  51. #define BTN_SETFILE 0
  52. #define BTN_EDITCAP 1
  53. #define BTN_LIVE 2
  54. #define BTN_CAPFRAME 3
  55. #define BTN_CAPSEL 4
  56. #define BTN_CAPAVI 5
  57. #define BTN_CAPPAL 6
  58. #define BTN_OVERLAY 7
  59. static int aiButton[] = {BTN_SETFILE, BTN_EDITCAP,
  60. BTN_LIVE, BTN_OVERLAY, BTN_CAPFRAME,
  61. BTN_CAPSEL, BTN_CAPAVI, BTN_CAPPAL };
  62. static int aiState[] = {BTNST_FOCUSUP, BTNST_UP,
  63. BTNST_UP, BTNST_UP, BTNST_UP,
  64. BTNST_UP, BTNST_UP, BTNST_UP};
  65. static int aiType[] ={BTNTYPE_PUSH, BTNTYPE_PUSH,
  66. BTNTYPE_CHECKBOX, BTNTYPE_CHECKBOX,
  67. BTNTYPE_PUSH,
  68. BTNTYPE_PUSH, BTNTYPE_PUSH, BTNTYPE_PUSH};
  69. static int aiString[] = { IDC_toolbarSETFILE,
  70. IDC_toolbarEDITCAP, IDC_toolbarLIVE,
  71. IDC_toolbarOVERLAY,
  72. IDC_toolbarCAPFRAME, IDC_toolbarCAPSEL,
  73. IDC_toolbarCAPAVI, IDC_toolbarCAPPAL };
  74. static int aPos[] = { 10, 35, 75, 100, 150, 175, 200, 225 };
  75. //
  76. // Global Variables
  77. //
  78. // preferences
  79. BOOL gbCentre;
  80. BOOL gbToolBar;
  81. BOOL gbStatusBar;
  82. BOOL gbAutoSizeFrame;
  83. int gBackColour;
  84. BOOL gbLive, gbOverlay;
  85. BOOL gfIsRTL;
  86. // saved window sizes
  87. int gWinX, gWinY;
  88. int gWinCX, gWinCY;
  89. int gWinShow;
  90. // command line options
  91. int gCmdLineDeviceID = -1;
  92. TCHAR gachAppName[] = "vidcapApp" ;
  93. TCHAR gachIconName[] = "vidcapIcon" ;
  94. TCHAR gachMenuName[] = "vidcapMenu" ;
  95. TCHAR gachAppTitle[20]; //VidCap
  96. TCHAR gachCaptureFile[_MAX_PATH];
  97. TCHAR gachMCIDeviceName[21];
  98. TCHAR gachString[128] ;
  99. TCHAR gachBuffer[200] ;
  100. TCHAR gachLastError[256];
  101. HINSTANCE ghInstApp ;
  102. HWND ghWndMain = NULL ;
  103. HWND ghWndFrame; // child of ghWndMain - frames and scrolls
  104. HWND ghWndCap ; // child of ghWndCap
  105. HWND ghWndToolBar;
  106. HWND ghWndStatus;
  107. HANDLE ghAccel ;
  108. WORD gwDeviceIndex ;
  109. WORD gwPalFrames = DEF_PALNUMFRAMES ;
  110. WORD gwPalColors = DEF_PALNUMCOLORS ;
  111. WORD gwCapFileSize ;
  112. CAPSTATUS gCapStatus ;
  113. CAPDRIVERCAPS gCapDriverCaps ;
  114. CAPTUREPARMS gCapParms ;
  115. BOOL gbHaveHardware;
  116. UINT gDriverCount;
  117. BOOL gbIsScrncap; // For Scrncap.drv, we must yield
  118. BOOL gbInLayout;
  119. UINT gAVStreamMaster;
  120. HANDLE ghwfex ;
  121. LPWAVEFORMATEX glpwfex ;
  122. FARPROC fpErrorCallback ;
  123. FARPROC fpStatusCallback ;
  124. FARPROC fpYieldCallback ;
  125. // set to false when we capture a palette (or if we have warned him and
  126. // he says its ok
  127. BOOL bDefaultPalette = TRUE;
  128. #ifdef DEBUG
  129. int nTestCount;
  130. #endif
  131. // c-runtime cmd line
  132. extern char ** __argv;
  133. extern int __argc;
  134. #define LimitRange(Val,Low,Hi) (max(Low,(min(Val,Hi))))
  135. //
  136. // Function prototypes
  137. //
  138. LRESULT FAR PASCAL MainWndProc(HWND, UINT, WPARAM, LPARAM) ;
  139. LRESULT FAR PASCAL ErrorCallbackProc(HWND, int, LPSTR) ;
  140. LRESULT FAR PASCAL StatusCallbackProc(HWND, int, LPSTR) ;
  141. LRESULT FAR PASCAL YieldCallbackProc(HWND) ;
  142. void vidcapSetLive(BOOL bLive);
  143. void vidcapSetOverlay(BOOL bOverlay);
  144. void vidcapSetCaptureFile(LPTSTR pFileName);
  145. BOOL vidcapRegisterClasses(HINSTANCE hInstance, HINSTANCE hPrevInstance);
  146. BOOL vidcapCreateWindows(HINSTANCE hInstance, HINSTANCE hPrevInstance);
  147. void vidcapLayout(HWND hwnd);
  148. BOOL vidcapEnumerateDrivers(HWND hwnd);
  149. BOOL vidcapInitHardware(HWND hwnd, HWND hwndCap, UINT uIndex);
  150. void vidcapReadProfile(void);
  151. void vidcapWriteProfile(void);
  152. void vidcapReadSettingsProfile(void);
  153. void vidcapWriteSettingsProfile(void);
  154. /* --- initialisation -------------------------------------------------- */
  155. //
  156. // WinMain: Application Entry Point Function
  157. //
  158. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  159. {
  160. ///////////////////////////////////////////////////////////////////////
  161. // hInstance: handle for this instance
  162. // hPrevInstance: handle for possible previous instances
  163. // lpszCmdLine: long pointer to exec command line
  164. // nCmdShow: Show code for main window display
  165. ///////////////////////////////////////////////////////////////////////
  166. MSG msg ;
  167. BOOL bValidCmdline;
  168. BOOL fOK;
  169. int i;
  170. char ach[2];
  171. ghInstApp = hInstance ;
  172. LoadString(hInstance, IDS_CAP_RTL, ach, sizeof(ach));
  173. gfIsRTL = ach[0] == '1';
  174. gCmdLineDeviceID = -1;
  175. // read the app title string - used in several message boxes
  176. LoadString(hInstance, IDS_APP_TITLE, gachAppTitle, sizeof(gachAppTitle));
  177. // read defaults out of the registry
  178. vidcapReadProfile();
  179. // look for cmd line options
  180. bValidCmdline = TRUE;
  181. for ( i = 1; (i < __argc) && bValidCmdline; i++) {
  182. if ((__argv[i][0] == '/') || (__argv[i][0] == '-')) {
  183. switch(__argv[i][1]) {
  184. case 'D':
  185. case 'd':
  186. if (gCmdLineDeviceID < 0) {
  187. // allow "-d0" and "-d 0"
  188. PSTR p = &__argv[i][2];
  189. if ((*p == 0) && ((i+1) < __argc)) {
  190. p = __argv[++i];
  191. }
  192. gCmdLineDeviceID = atoi(p);
  193. } else {
  194. bValidCmdline = FALSE;
  195. }
  196. break;
  197. default:
  198. bValidCmdline = FALSE;
  199. }
  200. } else {
  201. bValidCmdline = FALSE;
  202. }
  203. }
  204. if (gCmdLineDeviceID == -1)
  205. gCmdLineDeviceID = 0;
  206. if (!bValidCmdline) {
  207. MessageBoxID(IDS_ERR_CMDLINE, MB_OK|MB_ICONEXCLAMATION);
  208. return(0);
  209. }
  210. if (!vidcapRegisterClasses(hInstance, hPrevInstance)) {
  211. MessageBoxID(IDS_ERR_REGISTER_CLASS,
  212. #ifdef BIDI
  213. MB_RTL_READING |
  214. #endif
  215. MB_ICONEXCLAMATION) ;
  216. return 0 ;
  217. }
  218. if (!vidcapCreateWindows(hInstance, hPrevInstance)) {
  219. MessageBoxID(IDS_ERR_CREATE_WINDOW,
  220. #ifdef BIDI
  221. MB_RTL_READING |
  222. #endif
  223. MB_ICONEXCLAMATION | MB_OK) ;
  224. return IDS_ERR_CREATE_WINDOW ;
  225. }
  226. // Get the default setup for video capture from the AVICap window
  227. capCaptureGetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  228. // Overwrite the defaults with settings we have saved in the profile
  229. vidcapReadSettingsProfile();
  230. // Show the main window before connecting the hardware as this can be
  231. // time consuming and the user should see something happening first...
  232. ShowWindow(ghWndMain, nCmdShow) ;
  233. UpdateWindow(ghWndMain) ;
  234. ghAccel = LoadAccelerators(hInstance, "VIDCAP") ;
  235. // Create a list of all capture drivers and append them to the Options menu
  236. if (!(fOK = vidcapEnumerateDrivers(ghWndMain))) {
  237. LoadString(ghInstApp, IDS_ERR_FIND_HARDWARE, gachLastError, sizeof(gachLastError)/sizeof(*gachLastError));
  238. }
  239. // Try to connect to a capture driver
  240. else if (fOK = vidcapInitHardware(ghWndMain, ghWndCap,
  241. bValidCmdline ? gCmdLineDeviceID : 0)) {
  242. // Hooray, we now have a capture driver connected!
  243. vidcapSetCaptureFile(gachCaptureFile);
  244. }
  245. if (!fOK) {
  246. if (!DoDialog(ghWndMain, IDD_NoCapHardware, NoHardwareDlgProc,
  247. (LONG_PTR) (LPSTR) gachLastError)) {
  248. // The user has asked to abort, since no driver was available
  249. PostMessage(ghWndMain, WM_COMMAND,
  250. GET_WM_COMMAND_MPS(IDM_F_EXIT, 0, 0));
  251. }
  252. }
  253. // All set; get and process messages
  254. while (GetMessage(&msg, NULL, 0, 0)) {
  255. if (! TranslateAccelerator(ghWndMain, ghAccel, &msg)) {
  256. TranslateMessage(&msg) ;
  257. DispatchMessage(&msg) ;
  258. }
  259. }
  260. return (int) msg.wParam;
  261. } // End of WinMain
  262. BOOL
  263. vidcapRegisterClasses(HINSTANCE hInstance, HINSTANCE hPrevInstance)
  264. {
  265. WNDCLASS wc;
  266. if (! hPrevInstance) {
  267. // If it's the first instance, register the window class
  268. wc.lpszClassName = gachAppName ;
  269. wc.hInstance = hInstance ;
  270. wc.lpfnWndProc = MainWndProc ;
  271. wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
  272. wc.hIcon = LoadIcon(hInstance, gachIconName) ;
  273. wc.lpszMenuName = gachMenuName ;
  274. wc.hbrBackground = GetStockObject(WHITE_BRUSH) ;
  275. wc.style = CS_HREDRAW | CS_VREDRAW ;
  276. wc.cbClsExtra = 0 ;
  277. wc.cbWndExtra = 0 ;
  278. if (!RegisterClass(&wc)) {
  279. return(FALSE);
  280. }
  281. if (!ArrowInit(hInstance)) {
  282. return(FALSE);
  283. }
  284. if (!RLMeter_Register(hInstance)) {
  285. return(FALSE);
  286. }
  287. }
  288. if (!toolbarInit(hInstance, hPrevInstance)) {
  289. return(FALSE);
  290. }
  291. if (!statusInit(hInstance, hPrevInstance)) {
  292. return(FALSE);
  293. }
  294. return(TRUE);
  295. }
  296. BOOL
  297. vidcapCreateWindows(HINSTANCE hInstance, HINSTANCE hPrevInstance)
  298. {
  299. POINT pt;
  300. RECT rc;
  301. TOOLBUTTON tb;
  302. int i;
  303. // Create Application's Main window
  304. ghWndMain = CreateWindowEx(
  305. gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0,
  306. gachAppName,
  307. gachAppTitle,
  308. WS_CAPTION |
  309. WS_SYSMENU |
  310. WS_MINIMIZEBOX |
  311. WS_MAXIMIZEBOX |
  312. WS_THICKFRAME |
  313. WS_CLIPCHILDREN |
  314. WS_OVERLAPPED,
  315. gWinX, gWinY,
  316. gWinCX, gWinCY,
  317. NULL,
  318. NULL,
  319. hInstance,
  320. 0) ;
  321. if (ghWndMain == NULL) {
  322. return(FALSE);
  323. }
  324. /*
  325. * create a vidframe child window - this will create a child
  326. * AVICAP window within itself.
  327. *
  328. * Don't worry about size and position - vidcapLayout will do this
  329. * later (once we know the video format size).
  330. */
  331. ghWndFrame = vidframeCreate(
  332. ghWndMain,
  333. hInstance,
  334. hPrevInstance,
  335. 0, 0, 0, 0,
  336. &ghWndCap);
  337. if ((ghWndFrame == NULL) || (ghWndCap == NULL)) {
  338. return(FALSE);
  339. }
  340. // Register the status and error callbacks before driver connects
  341. // so we can get feedback about the connection process
  342. fpErrorCallback = MakeProcInstance((FARPROC)ErrorCallbackProc, ghInstApp) ;
  343. capSetCallbackOnError(ghWndCap, fpErrorCallback) ;
  344. fpStatusCallback = MakeProcInstance((FARPROC)StatusCallbackProc, ghInstApp) ;
  345. capSetCallbackOnStatus(ghWndCap, fpStatusCallback) ;
  346. // We'll only install a yield callback later if using Scrncap.drv
  347. fpYieldCallback = MakeProcInstance((FARPROC)YieldCallbackProc, ghInstApp) ;
  348. /*
  349. * CREATE THE TOOL BAR WINDOW
  350. */
  351. /* NOTE: let vidcapLayout() position it */
  352. ghWndToolBar = CreateWindowEx(
  353. gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0,
  354. szToolBarClass,
  355. NULL,
  356. WS_CHILD|WS_BORDER|WS_VISIBLE|WS_TABSTOP|
  357. WS_CLIPSIBLINGS,
  358. 0, 0,
  359. 0, 0,
  360. ghWndMain,
  361. NULL,
  362. hInstance,
  363. NULL);
  364. if (ghWndToolBar == NULL) {
  365. return(FALSE);
  366. }
  367. /* set the bitmap and button size to be used for this toolbar */
  368. pt.x = BUTTONWIDTH;
  369. pt.y = BUTTONHEIGHT;
  370. toolbarSetBitmap(ghWndToolBar, hInstance, IDBMP_TOOLBAR, pt);
  371. for (i = 0; i < APP_NUMTOOLS; i++) {
  372. rc.left = aPos[i];
  373. rc.top = 2;
  374. rc.right = rc.left + pt.x;
  375. rc.bottom = rc.top + pt.y;
  376. tb.rc = rc;
  377. tb.iButton = aiButton[i];
  378. tb.iState = aiState[i];
  379. tb.iType = aiType[i];
  380. tb.iString = aiString[i];
  381. toolbarAddTool(ghWndToolBar, tb);
  382. }
  383. // create the status bar - let vidcapLayout do the positioning
  384. ghWndStatus = CreateWindowEx(
  385. gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0,
  386. szStatusClass,
  387. NULL,
  388. WS_CHILD|WS_BORDER|WS_VISIBLE|WS_CLIPSIBLINGS,
  389. 0, 0,
  390. 0, 0,
  391. ghWndMain,
  392. NULL,
  393. hInstance,
  394. NULL);
  395. if (ghWndStatus == NULL) {
  396. return(FALSE);
  397. }
  398. return(TRUE);
  399. }
  400. /*
  401. * Enumerate the potential capture drivers and add the list to the Options
  402. * menu. This function is only called once at startup.
  403. * Returns FALSE if no drivers are available.
  404. */
  405. BOOL
  406. vidcapEnumerateDrivers(HWND hwnd)
  407. {
  408. TCHAR achDeviceVersion[80] ;
  409. TCHAR achDeviceAndVersion[160] ;
  410. UINT uIndex ;
  411. HMENU hMenuSub;
  412. gDriverCount = 0 ;
  413. hMenuSub = GetSubMenu (GetMenu (hwnd), 2); // Options menu
  414. for (uIndex = 0 ; uIndex < MAXVIDDRIVERS ; uIndex++) {
  415. if (capGetDriverDescription(uIndex,
  416. (LPSTR)achDeviceAndVersion, sizeof(achDeviceAndVersion),
  417. (LPSTR)achDeviceVersion, sizeof(achDeviceVersion))) {
  418. // Concatenate the device name and version strings
  419. lstrcat (achDeviceAndVersion, ", ");
  420. lstrcat (achDeviceAndVersion, achDeviceVersion);
  421. AppendMenu (hMenuSub,
  422. MF_STRING,
  423. IDM_O_DRIVER0 + uIndex,
  424. achDeviceAndVersion);
  425. gDriverCount++;
  426. }
  427. else
  428. break;
  429. }
  430. // Now refresh menu, position capture window, start driver etc
  431. DrawMenuBar(ghWndMain) ;
  432. return (gDriverCount);
  433. }
  434. /*
  435. * Connect the capture window to a capture driver.
  436. * uIndex specifies the index of the driver to use.
  437. * Returns TRUE on success, or FALSE if the driver connection failed.
  438. */
  439. BOOL
  440. vidcapInitHardware(HWND hwnd, HWND hwndCap, UINT uIndex)
  441. {
  442. UINT uError ;
  443. UINT uI;
  444. HMENU hMenu;
  445. TCHAR szName[MAX_PATH];
  446. TCHAR szVersion[MAX_PATH];
  447. // Since the driver may not provide a reliable error string
  448. // provide a default
  449. LoadString(ghInstApp, IDS_ERR_FIND_HARDWARE, gachLastError, sizeof(gachLastError)/sizeof(*gachLastError));
  450. // Try connecting to the capture driver
  451. if (uError = capDriverConnect(hwndCap, uIndex)) {
  452. gbHaveHardware = TRUE;
  453. gwDeviceIndex = (WORD) uIndex;
  454. }
  455. else {
  456. gbHaveHardware = FALSE;
  457. gbLive = FALSE;
  458. gbOverlay = FALSE;
  459. }
  460. // Get the capabilities of the capture driver
  461. capDriverGetCaps(hwndCap, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)) ;
  462. // Get the settings for the capture window
  463. capGetStatus(hwndCap, &gCapStatus , sizeof(gCapStatus));
  464. // Modify the toolbar buttons
  465. toolbarModifyState(ghWndToolBar, BTN_CAPFRAME,
  466. gbHaveHardware ? BTNST_UP : BTNST_GRAYED);
  467. toolbarModifyState(ghWndToolBar, BTN_CAPSEL,
  468. gbHaveHardware ? BTNST_UP : BTNST_GRAYED);
  469. toolbarModifyState(ghWndToolBar, BTN_CAPAVI,
  470. gbHaveHardware ? BTNST_UP : BTNST_GRAYED);
  471. toolbarModifyState(ghWndToolBar, BTN_LIVE,
  472. gbHaveHardware ? BTNST_UP : BTNST_GRAYED);
  473. // Is overlay supported?
  474. toolbarModifyState(ghWndToolBar, BTN_OVERLAY,
  475. (gbHaveHardware && gCapDriverCaps.fHasOverlay) ?
  476. BTNST_UP : BTNST_GRAYED);
  477. // Can the device create palettes?
  478. toolbarModifyState(ghWndToolBar, BTN_CAPPAL,
  479. (gbHaveHardware && gCapDriverCaps.fDriverSuppliesPalettes) ?
  480. BTNST_UP : BTNST_GRAYED);
  481. // Check the appropriate driver in the Options menu
  482. hMenu = GetMenu (hwnd);
  483. for (uI = 0; uI < gDriverCount; uI++) {
  484. CheckMenuItem (hMenu, IDM_O_DRIVER0 + uI,
  485. MF_BYCOMMAND | ((uIndex == uI) ? MF_CHECKED : MF_UNCHECKED));
  486. }
  487. // Unlike all other capture drivers, Scrncap.drv needs to use
  488. // a Yield callback, and we don't want to abort on mouse clicks,
  489. // so determine if the current driver is Scrncap.drv
  490. capGetDriverDescription (uIndex,
  491. szName, sizeof (szName),
  492. szVersion, sizeof (szVersion));
  493. // Set a flag if we're using Scrncap.drv
  494. gbIsScrncap = (_tcsstr (szName, "Screen Capture") != NULL);
  495. // Get video format and adjust capture window
  496. vidcapLayout(ghWndMain);
  497. InvalidateRect(ghWndMain, NULL, TRUE);
  498. // set the preview rate (units are millisecs)
  499. capPreviewRate(hwndCap, gbHaveHardware ? 33 : 0);
  500. // set live/overlay to default
  501. vidcapSetLive(gbLive);
  502. vidcapSetOverlay(gbOverlay);
  503. _tcscat (szName, ", ");
  504. _tcscat (szName, szVersion);
  505. statusUpdateStatus(ghWndStatus,
  506. gbHaveHardware ? szName : gachLastError);
  507. return gbHaveHardware;
  508. }
  509. /*
  510. * layout the main window. Put the toolbar at the top and the status
  511. * line at the bottom, and then give all the rest to vidframe,
  512. * - it will centre or scroll the AVICAP window appropriately.
  513. */
  514. void
  515. vidcapLayout(HWND hwnd)
  516. {
  517. RECT rc;
  518. RECT rw;
  519. int cy;
  520. int cyBorder, cxBorder;
  521. int cyTotal;
  522. int cxToolbar;
  523. int cyMenuAndToolbarAndCaption;
  524. gbInLayout = TRUE; // So that we process WM_GETMINMAXINFO normally
  525. /* for both the toolbar and status bar window,
  526. * we want just one of the four borders. We do this
  527. * by setting the WS_BORDER style, and sizing and positioning
  528. * the window so that the 3 unwanted borders are outside the parent.
  529. */
  530. cyBorder = GetSystemMetrics(SM_CYBORDER);
  531. cxBorder = GetSystemMetrics(SM_CXBORDER);
  532. // Figure out the height of the menu, toolbar, and caption
  533. GetWindowRect (hwnd, &rw);
  534. GetClientRect (hwnd, &rc);
  535. ClientToScreen (hwnd, (LPPOINT) &rc);
  536. cyMenuAndToolbarAndCaption = (rc.top - rw.top) + TOOLBAR_HEIGHT;
  537. cxToolbar = aPos[APP_NUMTOOLS - 1] + BUTTONWIDTH * 3;
  538. if (gbAutoSizeFrame && gbHaveHardware && gCapStatus.uiImageWidth) {
  539. cyTotal = gCapStatus.uiImageHeight +
  540. cyMenuAndToolbarAndCaption +
  541. (gbStatusBar ? statusGetHeight() : 0) +
  542. cyBorder * 2 +
  543. 12; // vidFrame height
  544. // Never make the frame smaller than the toolbar
  545. if (gCapStatus.uiImageWidth >= (UINT) cxToolbar) {
  546. SetWindowPos(
  547. hwnd,
  548. 0, // placement-order handle
  549. 0, // horizontal position
  550. 0, // vertical position
  551. gCapStatus.uiImageWidth + cxBorder * 24, // width
  552. cyTotal, // height
  553. SWP_NOZORDER | SWP_NOMOVE // window-positioning flags
  554. );
  555. } else {
  556. SetWindowPos(
  557. hwnd,
  558. 0, // placement-order handle
  559. 0, // horizontal position
  560. 0, // vertical position
  561. cxToolbar, // width
  562. cyTotal, // height
  563. SWP_NOZORDER | SWP_NOMOVE // window-positioning flags
  564. );
  565. }
  566. }
  567. GetClientRect(hwnd, &rc);
  568. if (gbToolBar) {
  569. // put the toolbar at the top - in fact, just off the top so as to
  570. // hide it's border
  571. MoveWindow(
  572. ghWndToolBar,
  573. -cxBorder, -cyBorder,
  574. RECTWIDTH(rc)+ (cxBorder * 2),
  575. TOOLBAR_HEIGHT,
  576. TRUE);
  577. rc.top += (TOOLBAR_HEIGHT - cyBorder);
  578. } else {
  579. MoveWindow(ghWndToolBar, 0, 0, 0, 0, TRUE);
  580. }
  581. // status bar at the bottom
  582. if (gbStatusBar) {
  583. cy = statusGetHeight() + cyBorder;
  584. MoveWindow(
  585. ghWndStatus,
  586. -cxBorder, rc.bottom - cy,
  587. RECTWIDTH(rc) + (2 * cxBorder), cy + cyBorder,
  588. TRUE);
  589. rc.bottom -= cy;
  590. } else {
  591. MoveWindow(ghWndStatus, 0, 0, 0, 0, TRUE);
  592. }
  593. // rest of window goes to vidframe window
  594. MoveWindow(
  595. ghWndFrame,
  596. rc.left, rc.top,
  597. RECTWIDTH(rc), RECTHEIGHT(rc),
  598. TRUE);
  599. // Always layout the frame window, since it is aligned on a
  600. // DWORD boundary for maximum codec drawing efficiency
  601. vidframeLayout(ghWndFrame, ghWndCap);
  602. gbInLayout = FALSE;
  603. }
  604. /*
  605. * initialise settings from the profile used before window creation time
  606. */
  607. void
  608. vidcapReadProfile(void)
  609. {
  610. // read defaults out of the registry
  611. gbCentre = mmGetProfileFlag(gachAppTitle, "CenterImage", TRUE);
  612. gbToolBar = mmGetProfileFlag(gachAppTitle, "ToolBar", TRUE);
  613. gbStatusBar = mmGetProfileFlag(gachAppTitle, "StatusBar", TRUE);
  614. gbAutoSizeFrame = mmGetProfileFlag(gachAppTitle, "AutoSizeFrame", TRUE);
  615. gBackColour = mmGetProfileInt(gachAppTitle, "BackgroundColor", IDD_PrefsLtGrey);
  616. gWinX = mmGetProfileInt(gachAppTitle, "WindowXPos", (UINT) CW_USEDEFAULT);
  617. if (gWinX != (UINT) CW_USEDEFAULT)
  618. gWinX = LimitRange(gWinX, 0, GetSystemMetrics (SM_CXSCREEN) - 40);
  619. gWinY = mmGetProfileInt(gachAppTitle, "WindowYPos", 0);
  620. gWinY = LimitRange(gWinY, 0, GetSystemMetrics (SM_CYSCREEN) - 40);
  621. gWinCX = mmGetProfileInt(gachAppTitle, "WindowWidth", 320);
  622. gWinCX = LimitRange(gWinCX, 20, GetSystemMetrics (SM_CXSCREEN));
  623. gWinCY = mmGetProfileInt(gachAppTitle, "WindowHeight", 240);
  624. gWinCY = LimitRange(gWinCY, 20, GetSystemMetrics (SM_CYSCREEN));
  625. gWinShow = mmGetProfileInt(gachAppTitle, "WindowShow", SW_SHOWDEFAULT);
  626. gWinShow = LimitRange(gWinShow, SW_SHOWNORMAL, SW_SHOWDEFAULT);
  627. gbOverlay = mmGetProfileInt(gachAppTitle, "OverlayWindow", FALSE);
  628. gbLive = mmGetProfileInt(gachAppTitle, "LiveWindow", TRUE);
  629. }
  630. void
  631. vidcapWriteProfile(void)
  632. {
  633. mmWriteProfileFlag(gachAppTitle, "CenterImage", gbCentre, TRUE);
  634. mmWriteProfileFlag(gachAppTitle, "ToolBar", gbToolBar, TRUE);
  635. mmWriteProfileFlag(gachAppTitle, "StatusBar", gbStatusBar, TRUE);
  636. mmWriteProfileFlag(gachAppTitle, "AutoSizeFrame", gbAutoSizeFrame, TRUE);
  637. mmWriteProfileInt(gachAppTitle, "BackgroundColor", gBackColour, IDD_PrefsLtGrey);
  638. mmWriteProfileInt(gachAppTitle, "WindowXPos", gWinX, (UINT) CW_USEDEFAULT);
  639. mmWriteProfileInt(gachAppTitle, "WindowYPos", gWinY, 0);
  640. mmWriteProfileInt(gachAppTitle, "WindowWidth", gWinCX, 320);
  641. mmWriteProfileInt(gachAppTitle, "WindowHeight", gWinCY, 240);
  642. mmWriteProfileInt(gachAppTitle, "WindowShow", gWinShow, SW_SHOWDEFAULT);
  643. mmWriteProfileInt(gachAppTitle, "OverlayWindow", gbOverlay, FALSE);
  644. mmWriteProfileInt(gachAppTitle, "LiveWindow", gbLive, TRUE);
  645. }
  646. /*
  647. * initialise settings from the profile used AFTER window creation time
  648. */
  649. void
  650. vidcapReadSettingsProfile(void)
  651. {
  652. DWORD dwSize;
  653. mmGetProfileString(gachAppTitle, "CaptureFile", "",
  654. gachCaptureFile, sizeof(gachCaptureFile));
  655. mmGetProfileString(gachAppTitle, "MCIDevice", "VideoDisc",
  656. gachMCIDeviceName, sizeof(gachMCIDeviceName));
  657. gCapParms.dwRequestMicroSecPerFrame =
  658. mmGetProfileInt(gachAppTitle, "MicroSecPerFrame",
  659. DEF_CAPTURE_RATE);
  660. gCapParms.dwRequestMicroSecPerFrame =
  661. mmGetProfileInt(gachAppTitle, "MicroSecPerFrame",
  662. DEF_CAPTURE_RATE);
  663. gCapParms.fCaptureAudio = mmGetProfileFlag(gachAppTitle, "CaptureAudio",
  664. gCapStatus.fAudioHardware);
  665. gCapParms.fLimitEnabled = mmGetProfileFlag(gachAppTitle, "LimitEnabled",
  666. FALSE);
  667. gCapParms.wTimeLimit =
  668. mmGetProfileInt(gachAppTitle, "TimeLimit", 30);
  669. gCapParms.fMCIControl= mmGetProfileFlag(gachAppTitle, "MCIControl", FALSE);
  670. gCapParms.fStepMCIDevice= mmGetProfileFlag(gachAppTitle, "StepMCIDevice", FALSE);
  671. gCapParms.dwMCIStartTime =
  672. mmGetProfileInt(gachAppTitle, "MCIStartTime", 10000);
  673. gCapParms.dwMCIStopTime =
  674. mmGetProfileInt(gachAppTitle, "MCIStopTime", 20000);
  675. gCapParms.fStepCaptureAt2x = mmGetProfileFlag(gachAppTitle, "StepCapture2x",
  676. FALSE);
  677. gCapParms.wStepCaptureAverageFrames =
  678. mmGetProfileInt(gachAppTitle, "StepCaptureAverageFrames", 3);
  679. gCapParms.AVStreamMaster = mmGetProfileInt (gachAppTitle, "AVStreamMaster",
  680. AVSTREAMMASTER_AUDIO);
  681. gCapParms.fUsingDOSMemory = mmGetProfileFlag (gachAppTitle, "CaptureToDisk",
  682. TRUE);
  683. gCapParms.dwIndexSize =
  684. mmGetProfileInt(gachAppTitle, "IndexSize",
  685. CAP_SMALL_INDEX);
  686. // Retrieve the saved audio format
  687. // Ask the ACM what the largest known wave format is
  688. acmMetrics(NULL,
  689. ACM_METRIC_MAX_SIZE_FORMAT,
  690. &dwSize);
  691. // If a wave format was saved in the registry, use that size
  692. dwSize = max (dwSize, mmGetProfileBinary(gachAppTitle, "WaveFormatBinary",
  693. NULL,
  694. NULL,
  695. 0));
  696. if (glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize)) {
  697. capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  698. mmGetProfileBinary(gachAppTitle, "WaveFormatBinary",
  699. glpwfex,
  700. glpwfex,
  701. dwSize);
  702. // Do some sanity checking
  703. if (MMSYSERR_NOERROR == waveInOpen (NULL, WAVE_MAPPER,
  704. glpwfex, 0, 0, WAVE_FORMAT_QUERY)) {
  705. capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  706. }
  707. GlobalFreePtr(glpwfex) ;
  708. }
  709. }
  710. void
  711. vidcapWriteSettingsProfile(void)
  712. {
  713. mmWriteProfileString(gachAppTitle, "CaptureFile", gachCaptureFile);
  714. mmWriteProfileString(gachAppTitle, "MCIDevice", gachMCIDeviceName);
  715. mmWriteProfileInt(gachAppTitle, "MicroSecPerFrame",
  716. gCapParms.dwRequestMicroSecPerFrame, DEF_CAPTURE_RATE);
  717. mmWriteProfileFlag(gachAppTitle, "CaptureAudio",
  718. gCapParms.fCaptureAudio, gCapStatus.fAudioHardware);
  719. mmWriteProfileFlag(gachAppTitle, "LimitEnabled",
  720. gCapParms.fLimitEnabled, FALSE);
  721. mmWriteProfileInt(gachAppTitle, "TimeLimit",
  722. gCapParms.wTimeLimit, 30);
  723. mmWriteProfileFlag(gachAppTitle, "MCIControl",
  724. gCapParms.fMCIControl, FALSE);
  725. mmWriteProfileFlag(gachAppTitle, "StepMCIDevice",
  726. gCapParms.fStepMCIDevice, FALSE);
  727. mmWriteProfileInt(gachAppTitle, "MCIStartTime",
  728. gCapParms.dwMCIStartTime, 10000);
  729. mmWriteProfileInt(gachAppTitle, "MCIStopTime",
  730. gCapParms.dwMCIStopTime, 20000);
  731. mmWriteProfileFlag(gachAppTitle, "StepCapture2x",
  732. gCapParms.fStepCaptureAt2x, FALSE);
  733. mmWriteProfileInt(gachAppTitle, "StepCaptureAverageFrames",
  734. gCapParms.wStepCaptureAverageFrames, 3);
  735. mmWriteProfileInt(gachAppTitle, "AVStreamMaster",
  736. gCapParms.AVStreamMaster, AVSTREAMMASTER_AUDIO);
  737. mmWriteProfileFlag(gachAppTitle, "CaptureToDisk",
  738. gCapParms.fUsingDOSMemory, TRUE);
  739. mmWriteProfileInt(gachAppTitle, "IndexSize",
  740. gCapParms.dwIndexSize, CAP_SMALL_INDEX);
  741. // The audio format is written whenever it is changed via dlg
  742. }
  743. /* --- error/status functions -------------------------------------------*/
  744. /*
  745. * put up a message box loading a string from the
  746. * resource file
  747. */
  748. int
  749. MessageBoxID(UINT idString, UINT fuStyle)
  750. {
  751. TCHAR achMessage[256]; // max message length
  752. LoadString(ghInstApp, idString, achMessage, sizeof(achMessage));
  753. return MessageBox(ghWndMain, achMessage, gachAppTitle, fuStyle);
  754. }
  755. //
  756. // ErrorCallbackProc: Error Callback Function
  757. //
  758. LRESULT FAR PASCAL ErrorCallbackProc(HWND hWnd, int nErrID, LPSTR lpErrorText)
  759. {
  760. ////////////////////////////////////////////////////////////////////////
  761. // hWnd: Application main window handle
  762. // nErrID: Error code for the encountered error
  763. // lpErrorText: Error text string for the encountered error
  764. ////////////////////////////////////////////////////////////////////////
  765. if (!ghWndMain)
  766. return FALSE;
  767. if (nErrID == 0) // Starting a new major function
  768. return TRUE; // Clear out old errors...
  769. // save the error message for use in NoHardwareDlgProc
  770. _tcscpy(gachLastError, lpErrorText);
  771. // Show the error ID and text
  772. MessageBox(hWnd, lpErrorText, gachAppTitle,
  773. #ifdef BIDI
  774. MB_RTL_READING |
  775. #endif
  776. MB_OK | MB_ICONEXCLAMATION) ;
  777. return (LRESULT) TRUE ;
  778. }
  779. //
  780. // StatusCallbackProc: Status Callback Function
  781. //
  782. LRESULT FAR PASCAL StatusCallbackProc(HWND hWnd, int nID, LPSTR lpStatusText)
  783. {
  784. ////////////////////////////////////////////////////////////////////////
  785. // hWnd: Application main window handle
  786. // nID: Status code for the current status
  787. // lpStatusText: Status text string for the current status
  788. ////////////////////////////////////////////////////////////////////////
  789. static int CurrentID;
  790. if (!ghWndMain) {
  791. return FALSE;
  792. }
  793. // the CAP_END message sometimes overwrites a useful
  794. // statistics message.
  795. if (nID == IDS_CAP_END) {
  796. if ((CurrentID == IDS_CAP_STAT_VIDEOAUDIO) ||
  797. (CurrentID == IDS_CAP_STAT_VIDEOONLY)) {
  798. return(TRUE);
  799. }
  800. }
  801. CurrentID = nID;
  802. statusUpdateStatus(ghWndStatus, lpStatusText);
  803. return (LRESULT) TRUE ;
  804. }
  805. //
  806. // YieldCallbackProc: Status Callback Function
  807. // (Only used for Scrncap.drv driver)
  808. //
  809. LRESULT FAR PASCAL YieldCallbackProc(HWND hWnd)
  810. {
  811. ////////////////////////////////////////////////////////////////////////
  812. // hWnd: Application main window handle
  813. ////////////////////////////////////////////////////////////////////////
  814. MSG msg;
  815. if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  816. TranslateMessage(&msg);
  817. DispatchMessage(&msg);
  818. }
  819. // Return TRUE to continue capturing
  820. return (LRESULT) TRUE;
  821. }
  822. /*
  823. * load a string from the string table and return
  824. * a pointer to it for temporary use. Each call
  825. * overwrites the previous
  826. */
  827. LPTSTR
  828. tmpString(UINT idString)
  829. {
  830. static TCHAR ach[350];
  831. LoadString(ghInstApp, idString, ach, sizeof(ach)/sizeof(TCHAR));
  832. // ensure null terminated
  833. ach[sizeof(ach) -1] = 0;
  834. return(ach);
  835. }
  836. /* --- connect to and init hardware ------------------------------------- */
  837. void
  838. vidcapSetLive(BOOL bLive)
  839. {
  840. capPreview(ghWndCap, bLive);
  841. toolbarModifyState(ghWndToolBar, BTN_LIVE, bLive? BTNST_DOWN : BTNST_UP);
  842. CheckMenuItem(GetMenu(ghWndMain), IDM_O_PREVIEW,
  843. MF_BYCOMMAND | (bLive ? MF_CHECKED : MF_UNCHECKED));
  844. gbLive = bLive;
  845. if (bLive == TRUE) {
  846. vidcapSetOverlay(FALSE);
  847. }
  848. }
  849. void
  850. vidcapSetOverlay(BOOL bOverlay)
  851. {
  852. if (!gCapDriverCaps.fHasOverlay) {
  853. CheckMenuItem(GetMenu(ghWndMain), IDM_O_OVERLAY,
  854. MF_BYCOMMAND | MF_UNCHECKED);
  855. gbOverlay = FALSE;
  856. return;
  857. }
  858. capOverlay(ghWndCap, bOverlay);
  859. toolbarModifyState(ghWndToolBar, BTN_OVERLAY, bOverlay ? BTNST_DOWN : BTNST_UP);
  860. CheckMenuItem(GetMenu(ghWndMain), IDM_O_OVERLAY,
  861. MF_BYCOMMAND | (bOverlay ? MF_CHECKED : MF_UNCHECKED));
  862. gbOverlay = bOverlay;
  863. if (bOverlay == TRUE) {
  864. vidcapSetLive(FALSE);
  865. }
  866. }
  867. void
  868. vidcapSetCaptureFile(LPTSTR pFileName)
  869. {
  870. TCHAR achBuffer[_MAX_PATH];
  871. if ((pFileName != NULL) && (_tcslen(pFileName) > 0)) {
  872. // record the capture filename
  873. if (_tcscmp(gachCaptureFile, pFileName)) {
  874. _tcscpy(gachCaptureFile, pFileName);
  875. }
  876. // and set window title
  877. wsprintf(achBuffer, "%s - %s", gachAppTitle, pFileName);
  878. } else {
  879. gachCaptureFile[0] = 0;
  880. _tcscpy(achBuffer, gachAppTitle);
  881. }
  882. capFileSetCaptureFile(ghWndCap, gachCaptureFile);
  883. SetWindowText(ghWndMain, achBuffer);
  884. }
  885. /* --- winproc and message handling --------------------------------------- */
  886. /*
  887. * called from WM_COMMAND processing if the
  888. * message is from the toolbar. iButton contains the
  889. * button ID in the lower 8 bits, and the flags in the upper 8 bits/
  890. */
  891. LONG FAR PASCAL
  892. toolbarCommand (HWND hWnd, int iButton, HWND hwndToolbar)
  893. {
  894. int iBtnPos, iState, iActivity, iString;
  895. // check repeat bit
  896. if (iButton & BTN_REPEAT) {
  897. return(0);
  898. }
  899. iButton &= 0xff;
  900. iBtnPos = toolbarIndexFromButton(hwndToolbar, iButton);
  901. iState = toolbarStateFromButton(hwndToolbar, iButton);
  902. iActivity = toolbarActivityFromButton(hwndToolbar, iButton);
  903. iString = toolbarStringFromIndex(hwndToolbar, iBtnPos);
  904. switch(iActivity) {
  905. case BTNACT_MOUSEDOWN:
  906. case BTNACT_KEYDOWN:
  907. case BTNACT_MOUSEMOVEON:
  908. statusUpdateStatus(ghWndStatus, MAKEINTRESOURCE(iString));
  909. break;
  910. case BTNACT_MOUSEMOVEOFF:
  911. statusUpdateStatus(ghWndStatus, NULL);
  912. break;
  913. case BTNACT_MOUSEUP:
  914. case BTNACT_KEYUP:
  915. statusUpdateStatus(ghWndStatus, NULL);
  916. switch(iButton) {
  917. case BTN_SETFILE:
  918. SendMessage(hWnd, WM_COMMAND,
  919. GET_WM_COMMAND_MPS(IDM_F_SETCAPTUREFILE, NULL, 0));
  920. break;
  921. case BTN_EDITCAP:
  922. // edit captured video
  923. SendMessage(hWnd, WM_COMMAND,
  924. GET_WM_COMMAND_MPS(IDM_F_EDITVIDEO, NULL, 0));
  925. break;
  926. case BTN_LIVE:
  927. SendMessage(hWnd,WM_COMMAND,
  928. GET_WM_COMMAND_MPS(IDM_O_PREVIEW, NULL, 0));
  929. break;
  930. case BTN_CAPFRAME:
  931. SendMessage(hWnd, WM_COMMAND,
  932. GET_WM_COMMAND_MPS(IDM_C_CAPTUREFRAME, NULL, 0));
  933. break;
  934. case BTN_CAPSEL:
  935. // capture selected frames
  936. SendMessage(hWnd, WM_COMMAND,
  937. GET_WM_COMMAND_MPS(IDM_C_CAPSEL, NULL, 0));
  938. break;
  939. case BTN_CAPAVI:
  940. SendMessage(hWnd,WM_COMMAND,
  941. GET_WM_COMMAND_MPS(IDM_C_CAPTUREVIDEO, NULL, 0));
  942. break;
  943. case BTN_CAPPAL:
  944. SendMessage(hWnd, WM_COMMAND,
  945. GET_WM_COMMAND_MPS(IDM_C_PALETTE, NULL, 0));
  946. break;
  947. case BTN_OVERLAY:
  948. SendMessage(hWnd, WM_COMMAND,
  949. GET_WM_COMMAND_MPS(IDM_O_OVERLAY, NULL, 0));
  950. break;
  951. }
  952. break;
  953. }
  954. return(0);
  955. }
  956. /*
  957. * Put up a dialog to allow the user to select a capture file.
  958. */
  959. LONG FAR PASCAL
  960. cmdSetCaptureFile(HWND hWnd)
  961. {
  962. OPENFILENAME ofn ;
  963. LPTSTR p;
  964. TCHAR achFileName[_MAX_PATH];
  965. TCHAR achBuffer[_MAX_PATH] ;
  966. UINT wError ;
  967. HANDLE hFilter;
  968. int oldhelpid;
  969. // Get current capture file name and
  970. // then try to get the new capture file name
  971. if (wError = capFileGetCaptureFile(ghWndCap, achFileName,
  972. sizeof(achFileName))) {
  973. // Get just the path info
  974. // Terminate the full path at the last backslash
  975. _tcscpy (achBuffer, achFileName);
  976. for (p = achBuffer + _tcslen(achBuffer); p > achBuffer; p--) {
  977. if (*p == '\\') {
  978. *(p+1) = '\0';
  979. break;
  980. }
  981. }
  982. _fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
  983. ofn.lStructSize = sizeof(OPENFILENAME) ;
  984. ofn.hwndOwner = hWnd ;
  985. //load filters from resource stringtable
  986. if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_AVI), RT_RCDATA))
  987. && (hFilter = LoadResource(ghInstApp, hFilter)) )
  988. {
  989. ofn.lpstrFilter = LockResource(hFilter);
  990. }
  991. else
  992. {
  993. ofn.lpstrFilter = NULL;
  994. }
  995. ofn.nFilterIndex = 0 ;
  996. ofn.lpstrFile = achFileName ;
  997. ofn.nMaxFile = sizeof(achFileName) ;
  998. ofn.lpstrFileTitle = NULL;
  999. ofn.lpstrTitle = tmpString(IDS_TITLE_SETCAPTUREFILE);
  1000. ofn.nMaxFileTitle = 0 ;
  1001. ofn.lpstrInitialDir = achBuffer;
  1002. ofn.Flags =
  1003. #ifdef BIDI
  1004. OFN_BIDIDIALOG |
  1005. #endif
  1006. OFN_HIDEREADONLY |
  1007. OFN_NOREADONLYRETURN |
  1008. OFN_PATHMUSTEXIST ;
  1009. // set help context for dialog
  1010. oldhelpid = SetCurrentHelpContext(IDA_SETCAPFILE);
  1011. if (GetOpenFileName(&ofn)) {
  1012. OFSTRUCT os;
  1013. vidcapSetCaptureFile(achFileName);
  1014. /*
  1015. * if this is a new file, then invite the user to
  1016. * allocate some space
  1017. */
  1018. if (OpenFile(achFileName, &os, OF_EXIST) == HFILE_ERROR) {
  1019. /*
  1020. * show the allocate file space dialog to encourage
  1021. * the user to pre-allocate space
  1022. */
  1023. if (DoDialog(hWnd, IDD_AllocCapFileSpace, AllocCapFileProc, 0)) {
  1024. // ensure repaint after dismissing dialog before
  1025. // possibly lengthy operation
  1026. UpdateWindow(ghWndMain);
  1027. // If user has hit OK then alloc requested capture file space
  1028. if (! capFileAlloc(ghWndCap, (long) gwCapFileSize * ONEMEG)) {
  1029. MessageBoxID(IDS_ERR_CANT_PREALLOC,
  1030. #ifdef BIDI
  1031. MB_RTL_READING |
  1032. #endif
  1033. MB_OK | MB_ICONEXCLAMATION) ;
  1034. }
  1035. }
  1036. }
  1037. }
  1038. // restore old help context
  1039. SetCurrentHelpContext(oldhelpid);
  1040. if (hFilter) {
  1041. UnlockResource(hFilter);
  1042. }
  1043. }
  1044. return(0);
  1045. }
  1046. /*
  1047. * query the user for a filename, and then save the captured video
  1048. * to that file
  1049. */
  1050. LONG FAR PASCAL
  1051. cmdSaveVideoAs(HWND hWnd)
  1052. {
  1053. OPENFILENAME ofn ;
  1054. TCHAR achFileName[_MAX_PATH];
  1055. UINT wError ;
  1056. HANDLE hFilter;
  1057. int oldhelpid;
  1058. // Get the current capture file name and
  1059. // then get the substitute file name to save video in
  1060. if (wError = capFileGetCaptureFile(ghWndCap, achFileName, sizeof(achFileName))) {
  1061. _fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
  1062. ofn.lStructSize = sizeof(OPENFILENAME) ;
  1063. ofn.hwndOwner = hWnd ;
  1064. //load filters from resource stringtable
  1065. if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_AVI), RT_RCDATA))
  1066. && (hFilter = LoadResource(ghInstApp, hFilter)) )
  1067. {
  1068. ofn.lpstrFilter = LockResource(hFilter);
  1069. }
  1070. else
  1071. {
  1072. ofn.lpstrFilter = NULL;
  1073. }
  1074. ofn.nFilterIndex = 0 ;
  1075. ofn.lpstrFile = achFileName ;
  1076. ofn.nMaxFile = sizeof(achFileName) ;
  1077. ofn.lpstrFileTitle = NULL ;
  1078. ofn.lpstrTitle = tmpString(IDS_TITLE_SAVEAS);
  1079. ofn.nMaxFileTitle = 0 ;
  1080. ofn.lpstrInitialDir = NULL ;
  1081. ofn.Flags =
  1082. #ifdef BIDI
  1083. OFN_BIDIDIALOG |
  1084. #endif
  1085. OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST ;
  1086. // set help context
  1087. oldhelpid = SetCurrentHelpContext(IDA_SAVECAPFILE);
  1088. if (GetSaveFileName(&ofn)) {
  1089. // If the user has hit OK then set save file name
  1090. capFileSaveAs(ghWndCap, achFileName) ;
  1091. }
  1092. SetCurrentHelpContext(oldhelpid);
  1093. if (hFilter) {
  1094. UnlockResource(hFilter);
  1095. }
  1096. }
  1097. return(0);
  1098. }
  1099. /*
  1100. * Put up a dialog to allow the user to select a palette file and then
  1101. * load that palette
  1102. */
  1103. LONG FAR PASCAL
  1104. cmdLoadPalette(HWND hWnd)
  1105. {
  1106. OPENFILENAME ofn ;
  1107. TCHAR achFileName[_MAX_PATH];
  1108. HANDLE hFilter;
  1109. int oldhelpid;
  1110. achFileName[0] = 0;
  1111. _fmemset(&ofn, 0, sizeof(OPENFILENAME));
  1112. ofn.lStructSize = sizeof(OPENFILENAME);
  1113. ofn.hwndOwner = hWnd;
  1114. //load filters from resource stringtable
  1115. if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_PALETTE), RT_RCDATA))
  1116. && (hFilter = LoadResource(ghInstApp, hFilter)) )
  1117. {
  1118. ofn.lpstrFilter = LockResource(hFilter);
  1119. }
  1120. else
  1121. {
  1122. ofn.lpstrFilter = NULL;
  1123. }
  1124. ofn.nFilterIndex = 1;
  1125. ofn.lpstrFile = achFileName;
  1126. ofn.nMaxFile = sizeof(achFileName);
  1127. ofn.lpstrFileTitle = NULL;
  1128. ofn.lpstrTitle = tmpString(IDS_TITLE_LOADPALETTE);
  1129. ofn.nMaxFileTitle = 0;
  1130. ofn.lpstrInitialDir = NULL;
  1131. ofn.Flags =
  1132. #ifdef BIDI
  1133. OFN_BIDIDIALOG |
  1134. #endif
  1135. OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  1136. // set help context id
  1137. oldhelpid = SetCurrentHelpContext(IDA_LOADPAL);
  1138. if (GetOpenFileName(&ofn)) {
  1139. // If the user has hit OK then load palette
  1140. capPaletteOpen(ghWndCap, achFileName);
  1141. }
  1142. SetCurrentHelpContext(oldhelpid);
  1143. if (hFilter) {
  1144. UnlockResource(hFilter);
  1145. }
  1146. return(0);
  1147. }
  1148. /*
  1149. * query the user for a filename, and then save the current palette
  1150. * to that file
  1151. */
  1152. LONG FAR PASCAL
  1153. cmdSavePalette(HWND hWnd)
  1154. {
  1155. OPENFILENAME ofn ;
  1156. TCHAR achFileName[_MAX_PATH];
  1157. HANDLE hFilter;
  1158. int oldhelpid;
  1159. achFileName[0] = 0;
  1160. _fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
  1161. ofn.lStructSize = sizeof(OPENFILENAME) ;
  1162. ofn.hwndOwner = hWnd ;
  1163. //load filters from resource stringtable
  1164. if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_PALETTE), RT_RCDATA))
  1165. && (hFilter = LoadResource(ghInstApp, hFilter)) )
  1166. {
  1167. ofn.lpstrFilter = LockResource(hFilter);
  1168. }
  1169. else
  1170. {
  1171. ofn.lpstrFilter = NULL;
  1172. }
  1173. ofn.nFilterIndex = 1;
  1174. ofn.lpstrFile = achFileName;
  1175. ofn.nMaxFile = sizeof(achFileName);
  1176. ofn.lpstrFileTitle = NULL;
  1177. ofn.lpstrTitle = tmpString(IDS_TITLE_SAVEPALETTE);
  1178. ofn.nMaxFileTitle = 0;
  1179. ofn.lpstrInitialDir = NULL;
  1180. ofn.Flags =
  1181. #ifdef BIDI
  1182. OFN_BIDIDIALOG |
  1183. #endif
  1184. OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
  1185. // set help context for F1 key
  1186. oldhelpid = SetCurrentHelpContext(IDA_SAVEPAL);
  1187. if (GetSaveFileName(&ofn)) {
  1188. // If the user has hit OK then set save file name
  1189. capPaletteSave(ghWndCap, achFileName);
  1190. }
  1191. SetCurrentHelpContext(oldhelpid);
  1192. if (hFilter) {
  1193. UnlockResource(hFilter);
  1194. }
  1195. return(0);
  1196. }
  1197. /*
  1198. * query the user for a filename, and then save the current frame
  1199. * to that file
  1200. */
  1201. LONG FAR PASCAL
  1202. cmdSaveDIB(HWND hWnd)
  1203. {
  1204. OPENFILENAME ofn ;
  1205. TCHAR achFileName[_MAX_PATH];
  1206. HANDLE hFilter;
  1207. int oldhelpid;
  1208. achFileName[0] = 0;
  1209. _fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
  1210. ofn.lStructSize = sizeof(OPENFILENAME) ;
  1211. ofn.hwndOwner = hWnd ;
  1212. //load filters from resource stringtable
  1213. if ( (hFilter = FindResource(ghInstApp, MAKEINTRESOURCE(ID_FILTER_DIB), RT_RCDATA) )
  1214. && (hFilter = LoadResource(ghInstApp, hFilter) ) )
  1215. {
  1216. ofn.lpstrFilter = LockResource(hFilter);
  1217. }
  1218. else
  1219. {
  1220. ofn.lpstrFilter = NULL;
  1221. }
  1222. ofn.nFilterIndex = 1;
  1223. ofn.lpstrFile = achFileName;
  1224. ofn.nMaxFile = sizeof(achFileName);
  1225. ofn.lpstrFileTitle = NULL;
  1226. ofn.lpstrTitle = tmpString(IDS_TITLE_SAVEDIB);
  1227. ofn.nMaxFileTitle = 0;
  1228. ofn.lpstrInitialDir = NULL;
  1229. ofn.Flags =
  1230. #ifdef BIDI
  1231. OFN_BIDIDIALOG |
  1232. #endif
  1233. OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
  1234. // set help context for F1 handling
  1235. oldhelpid = SetCurrentHelpContext(IDA_SAVEDIB);
  1236. if (GetSaveFileName(&ofn)) {
  1237. // If the user has hit OK then set save file name
  1238. capFileSaveDIB(ghWndCap, achFileName);
  1239. }
  1240. SetCurrentHelpContext(oldhelpid);
  1241. if (hFilter) {
  1242. UnlockResource(hFilter);
  1243. }
  1244. return(0);
  1245. }
  1246. //
  1247. // MenuProc: Processes All Menu-based Operations
  1248. //
  1249. LRESULT FAR PASCAL MenuProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
  1250. {
  1251. ////////////////////////////////////////////////////////////////////////
  1252. // hWnd: Application main window handle
  1253. // hMenu: Application menu handle
  1254. // wParam: Menu option
  1255. // lParam: Additional info for any menu option
  1256. ////////////////////////////////////////////////////////////////////////
  1257. BOOL fResult ;
  1258. DWORD dwSize = 0;
  1259. int oldhelpid;
  1260. HMENU hMenu = GetMenu(hWnd) ;
  1261. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  1262. case IDC_TOOLBAR:
  1263. return toolbarCommand(hWnd, GET_WM_COMMAND_CMD(wParam, lParam), ghWndToolBar);
  1264. /* --- file --- */
  1265. case IDM_F_SETCAPTUREFILE:
  1266. return cmdSetCaptureFile(hWnd);
  1267. case IDM_F_SAVEVIDEOAS:
  1268. return cmdSaveVideoAs(hWnd);
  1269. break;
  1270. case IDM_F_ALLOCATESPACE:
  1271. if (DoDialog(hWnd, IDD_AllocCapFileSpace, AllocCapFileProc, 0)) {
  1272. // ensure repaint after dismissing dialog before
  1273. // possibly lengthy operation
  1274. UpdateWindow(ghWndMain);
  1275. // If user has hit OK then alloc requested capture file space
  1276. if (! capFileAlloc(ghWndCap, (long) gwCapFileSize * ONEMEG)) {
  1277. MessageBoxID(IDS_ERR_CANT_PREALLOC,
  1278. #ifdef BIDI
  1279. MB_RTL_READING |
  1280. #endif
  1281. MB_OK | MB_ICONEXCLAMATION) ;
  1282. }
  1283. }
  1284. break ;
  1285. case IDM_F_EXIT:
  1286. DestroyWindow(hWnd) ;
  1287. break;
  1288. case IDM_F_LOADPALETTE:
  1289. return cmdLoadPalette(hWnd);
  1290. case IDM_F_SAVEPALETTE:
  1291. return cmdSavePalette(hWnd);
  1292. case IDM_F_SAVEFRAME:
  1293. return cmdSaveDIB(hWnd);
  1294. case IDM_F_EDITVIDEO:
  1295. {
  1296. HINSTANCE u;
  1297. BOOL f = TRUE; /* assume the best */
  1298. HCURSOR hOldCursor;
  1299. /* build up the command line "AviEdit -n filename" */
  1300. if (lstrlen(gachCaptureFile) > 0) {
  1301. hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1302. u = ShellExecute (hWnd, TEXT("open"), gachCaptureFile, NULL, NULL, SW_SHOWNORMAL);
  1303. if ((UINT_PTR) u < 32){
  1304. /* report error on forking VidEdit */
  1305. MessageBoxID(IDS_ERR_VIDEDIT, MB_OK|MB_ICONEXCLAMATION);
  1306. f = FALSE;
  1307. }
  1308. SetCursor(hOldCursor);
  1309. }
  1310. return f;
  1311. }
  1312. /* --- edit --- */
  1313. case IDM_E_COPY:
  1314. capEditCopy(ghWndCap) ;
  1315. break;
  1316. case IDM_E_PASTEPALETTE:
  1317. capPalettePaste(ghWndCap) ;
  1318. break;
  1319. case IDM_E_PREFS:
  1320. {
  1321. if (DoDialog(hWnd, IDD_Prefs, PrefsDlgProc, 0)) {
  1322. // write prefs to profile
  1323. // force new brush
  1324. vidframeSetBrush(ghWndFrame, gBackColour);
  1325. // re-do layout
  1326. vidcapLayout(hWnd);
  1327. }
  1328. }
  1329. break;
  1330. /* --- options --- */
  1331. case IDM_O_PREVIEW:
  1332. // Toggle Preview
  1333. capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  1334. vidcapSetLive(!gCapStatus.fLiveWindow) ;
  1335. break;
  1336. case IDM_O_OVERLAY:
  1337. // Toggle Overlay
  1338. capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  1339. vidcapSetOverlay(!gCapStatus.fOverlayWindow);
  1340. break ;
  1341. case IDM_O_AUDIOFORMAT:
  1342. #ifdef USE_ACM
  1343. {
  1344. ACMFORMATCHOOSE cfmt;
  1345. static BOOL fDialogUp = FALSE;
  1346. if (fDialogUp)
  1347. return FALSE;
  1348. fDialogUp = TRUE;
  1349. // Ask the ACM what the largest wave format is.....
  1350. acmMetrics(NULL,
  1351. ACM_METRIC_MAX_SIZE_FORMAT,
  1352. &dwSize);
  1353. // Get the current audio format
  1354. dwSize = max (dwSize, capGetAudioFormatSize (ghWndCap));
  1355. if (glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize)) {
  1356. capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  1357. _fmemset (&cfmt, 0, sizeof (ACMFORMATCHOOSE));
  1358. cfmt.cbStruct = sizeof (ACMFORMATCHOOSE);
  1359. cfmt.fdwStyle = ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT;
  1360. cfmt.fdwEnum = ACM_FORMATENUMF_HARDWARE |
  1361. ACM_FORMATENUMF_INPUT;
  1362. cfmt.hwndOwner = hWnd;
  1363. cfmt.pwfx = glpwfex;
  1364. cfmt.cbwfx = dwSize;
  1365. //oldhelpid = SetCurrentHelpContext(IDA_AUDIOSETUP);
  1366. if (!acmFormatChoose(&cfmt)) {
  1367. capSetAudioFormat(ghWndCap, glpwfex, (WORD)glpwfex->cbSize +
  1368. sizeof (WAVEFORMATEX)) ;
  1369. mmWriteProfileBinary(gachAppTitle, "WaveFormatBinary",
  1370. (LPVOID) glpwfex, glpwfex->cbSize +
  1371. sizeof (WAVEFORMATEX));
  1372. }
  1373. //SetCurrentHelpContext(oldhelpid);
  1374. GlobalFreePtr(glpwfex) ;
  1375. }
  1376. fDialogUp = FALSE;
  1377. }
  1378. #else
  1379. {
  1380. // Get current audio format and then find required format
  1381. dwSize = capGetAudioFormatSize (ghWndCap);
  1382. glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize) ;
  1383. capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  1384. if (DoDialog(hWnd, IDD_AudioFormat, AudioFormatProc, 0)) {
  1385. // If the user has hit OK, set the new audio format
  1386. capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  1387. mmWriteProfileBinary(gachAppTitle, "WaveFormatBinary",
  1388. (LPVOID) glpwfex, dwSize);
  1389. }
  1390. GlobalFreePtr(glpwfex) ;
  1391. }
  1392. #endif
  1393. break ;
  1394. case IDM_O_VIDEOFORMAT:
  1395. if (gCapDriverCaps.fHasDlgVideoFormat) {
  1396. // Only if the driver has a "Video Format" dialog box
  1397. oldhelpid = SetCurrentHelpContext(IDA_VIDFORMAT);
  1398. if (capDlgVideoFormat(ghWndCap)) { // If successful,
  1399. // Get the new image dimension and center capture window
  1400. capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  1401. vidcapLayout(hWnd);
  1402. }
  1403. SetCurrentHelpContext(oldhelpid);
  1404. }
  1405. break;
  1406. case IDM_O_VIDEOSOURCE:
  1407. if (gCapDriverCaps.fHasDlgVideoSource) {
  1408. // Only if the driver has a "Video Source" dialog box
  1409. oldhelpid = SetCurrentHelpContext(IDA_VIDSOURCE);
  1410. capDlgVideoSource(ghWndCap) ;
  1411. capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  1412. vidcapLayout(hWnd);
  1413. SetCurrentHelpContext(oldhelpid);
  1414. }
  1415. break ;
  1416. case IDM_O_VIDEODISPLAY:
  1417. if (gCapDriverCaps.fHasDlgVideoDisplay) {
  1418. // Only if the driver has a "Video Display" dialog box
  1419. oldhelpid = SetCurrentHelpContext(IDA_VIDDISPLAY);
  1420. capDlgVideoDisplay(ghWndCap) ;
  1421. capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  1422. SetCurrentHelpContext(oldhelpid);
  1423. }
  1424. break ;
  1425. case IDM_O_CHOOSECOMPRESSOR:
  1426. oldhelpid = SetCurrentHelpContext(IDA_COMPRESSION);
  1427. capDlgVideoCompression(ghWndCap);
  1428. SetCurrentHelpContext(oldhelpid);
  1429. break;
  1430. // Select a driver to activate
  1431. case IDM_O_DRIVER0:
  1432. case IDM_O_DRIVER1:
  1433. case IDM_O_DRIVER2:
  1434. case IDM_O_DRIVER3:
  1435. case IDM_O_DRIVER4:
  1436. case IDM_O_DRIVER5:
  1437. case IDM_O_DRIVER6:
  1438. case IDM_O_DRIVER7:
  1439. case IDM_O_DRIVER8:
  1440. case IDM_O_DRIVER9:
  1441. vidcapInitHardware(ghWndMain, ghWndCap, (UINT) (wParam - IDM_O_DRIVER0));
  1442. break;
  1443. /* --- capture --- */
  1444. case IDM_C_PALETTE:
  1445. if (DoDialog(hWnd, IDD_MakePalette, MakePaletteProc, 0)) {
  1446. // Palette is created within the dialog
  1447. bDefaultPalette = FALSE;
  1448. }
  1449. break;
  1450. case IDM_C_CAPTUREVIDEO:
  1451. // warn user if he is still using the default palette
  1452. if (bDefaultPalette) {
  1453. LPBITMAPINFOHEADER lpbi;
  1454. int sz;
  1455. // fUsingDefaultPalette will be TRUE even if the
  1456. // current capture format is non-palettised. This is a
  1457. // bizarre decision of Jay's.
  1458. sz = (int)capGetVideoFormatSize(ghWndCap);
  1459. lpbi = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, sz);
  1460. if (lpbi) { // We can warn s/he
  1461. if (capGetVideoFormat(ghWndCap, lpbi, sz) &&
  1462. (lpbi->biCompression == BI_RGB) &&
  1463. (lpbi->biBitCount <= 8)) {
  1464. CAPSTATUS cs;
  1465. // if we've warned him once, we can forget it
  1466. bDefaultPalette = FALSE;
  1467. capGetStatus(ghWndCap, &cs, sizeof(cs));
  1468. if (cs.fUsingDefaultPalette) {
  1469. if (MessageBoxID(IDS_WARN_DEFAULT_PALETTE,
  1470. MB_OKCANCEL| MB_ICONEXCLAMATION)== IDCANCEL) {
  1471. break;
  1472. }
  1473. }
  1474. }
  1475. LocalFree(lpbi);
  1476. }
  1477. }
  1478. // Invoke a Dlg box to setup all the params
  1479. if (DoDialog(hWnd, IDD_CapSetUp, CapSetUpProc, 0)) {
  1480. // set the defaults we won't bother the user with
  1481. gCapParms.fMakeUserHitOKToCapture = !gCapParms.fMCIControl;
  1482. gCapParms.wPercentDropForError = 10;
  1483. // fUsingDOSMemory is obsolete, but we use it here as
  1484. // a flag which is TRUE if "CapturingToDisk"
  1485. // The number of video buffers should be enough to get through
  1486. // disk seeks and thermal recalibrations if "CapturingToDisk"
  1487. // If "CapturingToMemory", get as many buffers as we can.
  1488. gCapParms.wNumVideoRequested =
  1489. gCapParms.fUsingDOSMemory ? 32 : 1000;
  1490. // Don't abort on the left mouse anymore!
  1491. gCapParms.fAbortLeftMouse = FALSE;
  1492. gCapParms.fAbortRightMouse = TRUE;
  1493. // If the Driver is Scrncap.drv, the following values are special
  1494. // If wChunkGranularity is zero, the granularity will be set to the
  1495. // disk sector size.
  1496. gCapParms.wChunkGranularity = (gbIsScrncap ? 32 : 0);
  1497. // Scrncap requires a callback for the message pump
  1498. capSetCallbackOnYield(ghWndCap,
  1499. (gbIsScrncap ? fpYieldCallback : NULL));
  1500. // If the user has hit OK, set the new setup info
  1501. capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  1502. } else {
  1503. break;
  1504. }
  1505. // if no capture file, get that
  1506. if (lstrlen(gachCaptureFile) <= 0) {
  1507. cmdSetCaptureFile(hWnd);
  1508. if (lstrlen(gachCaptureFile) <= 0) {
  1509. break;
  1510. }
  1511. }
  1512. // Capture video sequence
  1513. fResult = capCaptureSequence(ghWndCap) ;
  1514. break;
  1515. case IDM_C_CAPTUREFRAME:
  1516. // Turn off overlay / preview (gets turned off by frame capture)
  1517. vidcapSetLive(FALSE);
  1518. vidcapSetOverlay(FALSE);
  1519. // Grab a frame
  1520. fResult = capGrabFrameNoStop(ghWndCap) ;
  1521. break;
  1522. case IDM_C_CAPSEL:
  1523. {
  1524. //FARPROC fproc;
  1525. // if no capture file, get that
  1526. if (lstrlen(gachCaptureFile) <= 0) {
  1527. cmdSetCaptureFile(hWnd);
  1528. if (lstrlen(gachCaptureFile) <= 0) {
  1529. break;
  1530. }
  1531. }
  1532. //fproc = MakeProcInstance(CapFramesProc, ghInstApp);
  1533. DialogBox(ghInstApp, MAKEINTRESOURCE(IDD_CAPFRAMES), hWnd, CapFramesProc);
  1534. //FreeProcInstance(fproc);
  1535. }
  1536. break;
  1537. #ifdef DEBUG
  1538. case IDM_C_TEST:
  1539. nTestCount = 0;
  1540. // Intentional fall through
  1541. case IDM_C_TESTAGAIN:
  1542. // set the defaults we won't bother the user with
  1543. gCapParms.fMakeUserHitOKToCapture = FALSE;
  1544. gCapParms.wPercentDropForError = 100;
  1545. gCapParms.wNumVideoRequested =
  1546. gCapParms.fUsingDOSMemory ? 32 : 1000;
  1547. // Don't abort on the left mouse anymore!
  1548. gCapParms.fAbortLeftMouse = FALSE;
  1549. gCapParms.fAbortRightMouse = TRUE;
  1550. // If wChunkGranularity is zero, the granularity will be set to the
  1551. // disk sector size.
  1552. gCapParms.wChunkGranularity = (gbIsScrncap ? 32 : 0);
  1553. // If the user has hit OK, set the new setup info
  1554. capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  1555. // if no capture file, get that
  1556. if (lstrlen(gachCaptureFile) <= 0) {
  1557. cmdSetCaptureFile(hWnd);
  1558. if (lstrlen(gachCaptureFile) <= 0) {
  1559. break;
  1560. }
  1561. }
  1562. {
  1563. TCHAR buf[80];
  1564. gCapParms.wNumVideoRequested = 10;
  1565. gCapParms.wNumAudioRequested = 5;
  1566. gCapParms.fLimitEnabled = TRUE;
  1567. if (gCapParms.wTimeLimit == 0)
  1568. gCapParms.wTimeLimit = 5;
  1569. capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  1570. // Capture video sequence
  1571. fResult = capCaptureSequence(ghWndCap) ;
  1572. wsprintf (buf, "TestCount = %d", nTestCount++);
  1573. statusUpdateStatus(ghWndStatus, buf);
  1574. // Hold down the right mouse button to abort
  1575. if (!GetAsyncKeyState(VK_RBUTTON) & 0x0001)
  1576. PostMessage (hWnd, WM_COMMAND, IDM_C_TESTAGAIN, 0L);
  1577. }
  1578. break;
  1579. #endif
  1580. /* --- help --- */
  1581. case IDM_H_CONTENTS:
  1582. HelpContents();
  1583. break;
  1584. case IDM_H_ABOUT:
  1585. ShellAbout(
  1586. hWnd,
  1587. "VidCap",
  1588. "Video Capture Tool",
  1589. LoadIcon(ghInstApp, gachIconName)
  1590. );
  1591. //DoDialog(hWnd, IDD_HelpAboutBox, AboutProc, 0);
  1592. break ;
  1593. }
  1594. return 0L ;
  1595. }
  1596. /* --- menu help and enable/disable handling ------------------------ */
  1597. // write or clear status line help text when the user brings up or cancels a
  1598. // menu. This depends on there being strings in the string table with
  1599. // the same ID as the corresponding menu item.
  1600. // Help text for the items along the menu bar (File, Edit etc) depends
  1601. // on IDM_FILE, IDM_EDIT being defined with values 100 apart in the same
  1602. // order as their index in the menu
  1603. void
  1604. MenuSelect(HWND hwnd, UINT cmd, UINT flags, HMENU hmenu)
  1605. {
  1606. if ((LOWORD(flags) == 0xffff) && (hmenu == NULL)) {
  1607. //menu closing - remove message
  1608. statusUpdateStatus(ghWndStatus, NULL);
  1609. } else if ( (flags & (MF_SYSMENU|MF_POPUP)) == (MF_SYSMENU|MF_POPUP)) {
  1610. // the system menu itself
  1611. statusUpdateStatus(ghWndStatus, MAKEINTRESOURCE(IDM_SYSMENU));
  1612. } else if ((flags & MF_POPUP) == 0) {
  1613. // a menu command item
  1614. statusUpdateStatus(ghWndStatus, MAKEINTRESOURCE(cmd));
  1615. } else {
  1616. //a popup menu - we need to search to find which one.
  1617. // note that the cmd item in Win16 will now have a
  1618. // menu handle, whereas in Win32 it has an index.
  1619. // NOTE: this code assumes that the menu items
  1620. // are #defined 100 apart in the same order, starting
  1621. // with IDM_FILE
  1622. #ifdef _WIN32
  1623. statusUpdateStatus(ghWndStatus, MAKEINTRESOURCE(IDM_FILE + (cmd * 100)));
  1624. #else
  1625. int i,c;
  1626. HMENU hmenuMain;
  1627. hmenuMain = GetMenu(hWnd);
  1628. c = GetMenuItemCount(hmenuMain);
  1629. for(i = 0; i < c; i++) {
  1630. if (hmenu == GetSubMenu(hmenuMain, i)) {
  1631. statusUpdateStatus(MAKEINTRESOURCE(IDM_FILE + (cmd*100)));
  1632. return(0);
  1633. }
  1634. }
  1635. statusUpdateStatus(NULL);
  1636. #endif
  1637. }
  1638. }
  1639. // a popup menu is being selected - enable or disable menu items
  1640. int
  1641. InitMenuPopup(
  1642. HWND hwnd,
  1643. HMENU hmenu,
  1644. int index
  1645. )
  1646. {
  1647. int i = MF_ENABLED;
  1648. CAPSTATUS cs;
  1649. BOOL bUsesPalettes;
  1650. capGetStatus(ghWndCap, &cs, sizeof(cs));
  1651. // try to see if the driver uses palettes
  1652. if ((cs.hPalCurrent != NULL) || (cs.fUsingDefaultPalette)) {
  1653. bUsesPalettes = TRUE;
  1654. } else {
  1655. bUsesPalettes = FALSE;
  1656. }
  1657. switch(index) {
  1658. case 0: // IDM_FILE
  1659. if (lstrlen(gachCaptureFile) <= 0) {
  1660. i = MF_GRAYED;
  1661. }
  1662. // save as enabled only if we have a capture file
  1663. EnableMenuItem(hmenu, IDM_F_SAVEVIDEOAS, i);
  1664. // edit video possible only if we have a capture file AND we've
  1665. // captured something
  1666. EnableMenuItem(hmenu, IDM_F_EDITVIDEO,
  1667. (cs.dwCurrentVideoFrame > 0) ? i : MF_GRAYED);
  1668. // allow save palette if there is one
  1669. EnableMenuItem(hmenu, IDM_F_SAVEPALETTE,
  1670. (cs.hPalCurrent != NULL) ? MF_ENABLED:MF_GRAYED);
  1671. // allow load palette if the driver uses palettes
  1672. EnableMenuItem(hmenu, IDM_F_LOADPALETTE,
  1673. bUsesPalettes ? MF_ENABLED : MF_GRAYED);
  1674. break;
  1675. case 1: // IDM_EDIT
  1676. // paste palettes if driver uses them and there is one pastable
  1677. EnableMenuItem(hmenu, IDM_E_PASTEPALETTE,
  1678. (bUsesPalettes && IsClipboardFormatAvailable(CF_PALETTE)) ? MF_ENABLED:MF_GRAYED);
  1679. break;
  1680. case 2: // IDM_OPTIONS
  1681. EnableMenuItem(hmenu, IDM_O_AUDIOFORMAT,
  1682. cs.fAudioHardware ? MF_ENABLED : MF_GRAYED);
  1683. EnableMenuItem(hmenu, IDM_O_OVERLAY,
  1684. gCapDriverCaps.fHasOverlay ? MF_ENABLED:MF_GRAYED);
  1685. EnableMenuItem(hmenu, IDM_O_VIDEOFORMAT,
  1686. gCapDriverCaps.fHasDlgVideoFormat ? MF_ENABLED:MF_GRAYED);
  1687. EnableMenuItem(hmenu, IDM_O_VIDEODISPLAY,
  1688. gCapDriverCaps.fHasDlgVideoDisplay ? MF_ENABLED:MF_GRAYED);
  1689. EnableMenuItem(hmenu, IDM_O_VIDEOSOURCE,
  1690. gCapDriverCaps.fHasDlgVideoSource ? MF_ENABLED:MF_GRAYED);
  1691. EnableMenuItem(hmenu, IDM_O_PREVIEW,
  1692. gbHaveHardware ? MF_ENABLED:MF_GRAYED);
  1693. case 3: // IDM_CAPTURE
  1694. if (!gbHaveHardware) {
  1695. i = MF_GRAYED;
  1696. }
  1697. EnableMenuItem(hmenu, IDM_C_CAPSEL, i);
  1698. EnableMenuItem(hmenu, IDM_C_CAPTUREFRAME, i);
  1699. EnableMenuItem(hmenu, IDM_C_CAPTUREVIDEO, i);
  1700. EnableMenuItem(hmenu, IDM_C_PALETTE, (gbHaveHardware &&
  1701. gCapDriverCaps.fDriverSuppliesPalettes) ? MF_ENABLED : MF_GRAYED);
  1702. break;
  1703. }
  1704. return(0);
  1705. }
  1706. //
  1707. // MainWndProc: Application Main Window Procedure
  1708. //
  1709. LRESULT FAR PASCAL MainWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
  1710. {
  1711. ////////////////////////////////////////////////////////////////////////
  1712. // hWnd: Application main window handle
  1713. // Message: Next message to be processed
  1714. // wParam: WORD param for the message
  1715. // lParam: LONG param for the message
  1716. ////////////////////////////////////////////////////////////////////////
  1717. switch (Message) {
  1718. static BOOL fMinimized;
  1719. case WM_SYSCOMMAND:
  1720. if ((wParam & 0xfff0) == SC_MAXIMIZE)
  1721. fMinimized = FALSE;
  1722. else if ((wParam & 0xfff0) == SC_RESTORE)
  1723. fMinimized = FALSE;
  1724. else if ((wParam & 0xfff0) == SC_MINIMIZE)
  1725. fMinimized = TRUE;
  1726. return DefWindowProc(hWnd, Message, wParam, lParam);
  1727. break;
  1728. case WM_COMMAND:
  1729. MenuProc(hWnd, wParam, lParam) ;
  1730. break ;
  1731. case WM_CREATE:
  1732. HelpInit(ghInstApp, "vidcap.hlp", hWnd);
  1733. break;
  1734. case WM_NCHITTEST:
  1735. {
  1736. LRESULT dw;
  1737. dw = DefWindowProc(hWnd, Message, wParam, lParam);
  1738. // Don't allow border resize if autosizing
  1739. if (gbAutoSizeFrame) {
  1740. if (dw >= HTSIZEFIRST && dw <= HTSIZELAST)
  1741. dw = HTCAPTION;
  1742. }
  1743. return dw;
  1744. }
  1745. break;
  1746. case WM_GETMINMAXINFO:
  1747. // Don't allow manual sizing if window locked to the capture size
  1748. if (gbHaveHardware && gbAutoSizeFrame && !gbInLayout) {
  1749. RECT rW;
  1750. LPMINMAXINFO lpMMI = (LPMINMAXINFO) lParam;
  1751. GetWindowRect (hWnd, &rW);
  1752. lpMMI->ptMinTrackSize.x = rW.right - rW.left;
  1753. lpMMI->ptMinTrackSize.y = rW.bottom - rW.top;
  1754. lpMMI->ptMaxTrackSize = lpMMI->ptMinTrackSize;
  1755. }
  1756. break;
  1757. case WM_MOVE:
  1758. if (!fMinimized) {
  1759. vidcapLayout (hWnd);
  1760. }
  1761. break;
  1762. case WM_SIZE:
  1763. if (!fMinimized) {
  1764. vidcapLayout (hWnd);
  1765. }
  1766. break;
  1767. case WM_MENUSELECT:
  1768. {
  1769. UINT cmd = GET_WM_MENUSELECT_CMD(wParam, lParam);
  1770. UINT flags = GET_WM_MENUSELECT_FLAGS(wParam, lParam);
  1771. HMENU hmenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
  1772. MenuSelect(hWnd, cmd, flags, hmenu);
  1773. }
  1774. break;
  1775. case WM_INITMENUPOPUP:
  1776. {
  1777. BOOL bSystem = (BOOL) HIWORD(lParam);
  1778. if (!bSystem) {
  1779. return InitMenuPopup(hWnd,
  1780. (HMENU) wParam, (int) LOWORD(lParam));
  1781. } else {
  1782. return(DefWindowProc(hWnd, Message, wParam, lParam));
  1783. }
  1784. }
  1785. case WM_SYSCOLORCHANGE:
  1786. // we don't use this ourselves, but we should pass
  1787. // it on to all three children
  1788. SendMessage(ghWndFrame, Message, wParam, lParam);
  1789. SendMessage(ghWndToolBar, Message, wParam, lParam);
  1790. SendMessage(ghWndStatus, Message, wParam, lParam);
  1791. return (TRUE);
  1792. case WM_PALETTECHANGED:
  1793. case WM_QUERYNEWPALETTE:
  1794. // Pass the buck to Capture window proc
  1795. return SendMessage(ghWndCap, Message, wParam, lParam) ;
  1796. break ;
  1797. case WM_SETFOCUS:
  1798. // the toolbar is the only part that needs the focus
  1799. SetFocus(ghWndToolBar);
  1800. break;
  1801. case WM_ACTIVATEAPP:
  1802. if (wParam && ghWndCap)
  1803. capPreviewRate(ghWndCap, 15); // Fast preview when active
  1804. else
  1805. capPreviewRate(ghWndCap, 1000); // Slow preview when inactive
  1806. break;
  1807. case WM_NEXTDLGCTL:
  1808. // if anyone is tabbing about, move the focus to the
  1809. // toolbar
  1810. SetFocus(ghWndToolBar);
  1811. // select the correct button to handle moving off one
  1812. // end and back on the other end
  1813. if (lParam == FALSE) {
  1814. // are we moving forwards or backwards ?
  1815. if (wParam == 0) {
  1816. // move to next - so select first button
  1817. toolbarSetFocus(ghWndToolBar, TB_FIRST);
  1818. } else {
  1819. // move to previous - so select last
  1820. toolbarSetFocus(ghWndToolBar, TB_LAST);
  1821. }
  1822. }
  1823. break;
  1824. case WM_PAINT:
  1825. {
  1826. HDC hDC ;
  1827. PAINTSTRUCT ps ;
  1828. hDC = BeginPaint(hWnd, &ps) ;
  1829. // Included in case the background is not a pure color
  1830. SetBkMode(hDC, TRANSPARENT) ;
  1831. EndPaint(hWnd, &ps) ;
  1832. break ;
  1833. }
  1834. case WM_CLOSE:
  1835. // Disable and free all the callbacks
  1836. capSetCallbackOnError(ghWndCap, NULL) ;
  1837. if (fpErrorCallback) {
  1838. FreeProcInstance(fpErrorCallback) ;
  1839. fpErrorCallback = NULL;
  1840. }
  1841. capSetCallbackOnStatus(ghWndCap, NULL) ;
  1842. if (fpStatusCallback) {
  1843. FreeProcInstance(fpStatusCallback) ;
  1844. fpStatusCallback = NULL;
  1845. }
  1846. capSetCallbackOnYield(ghWndCap, NULL) ;
  1847. if (fpYieldCallback) {
  1848. FreeProcInstance(fpYieldCallback) ;
  1849. fpYieldCallback = NULL;
  1850. }
  1851. // Disconnect the current capture driver
  1852. capDriverDisconnect (ghWndCap);
  1853. // Destroy child windows, modeless dialogs, then this window...
  1854. // DestroyWindow(ghWndCap) ;
  1855. DestroyWindow(hWnd) ;
  1856. break ;
  1857. case WM_DESTROY:
  1858. {
  1859. // remember window size and position
  1860. // - this will be written to the profile
  1861. WINDOWPLACEMENT wp;
  1862. wp.length = sizeof (WINDOWPLACEMENT);
  1863. GetWindowPlacement(hWnd, &wp);
  1864. gWinShow = wp.showCmd;
  1865. gWinX = wp.rcNormalPosition.left;
  1866. gWinY = wp.rcNormalPosition.top;
  1867. gWinCX = RECTWIDTH(wp.rcNormalPosition);
  1868. gWinCY = RECTHEIGHT(wp.rcNormalPosition);
  1869. // write defaults out to the registry
  1870. vidcapWriteProfile();
  1871. vidcapWriteSettingsProfile();
  1872. HelpShutdown();
  1873. }
  1874. PostQuitMessage(0) ;
  1875. break ;
  1876. default:
  1877. return DefWindowProc(hWnd, Message, wParam, lParam) ;
  1878. }
  1879. return 0L;
  1880. } // End of MainWndProc