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.

653 lines
18 KiB

  1. /****************************************************************************
  2. *
  3. * MODULE : PREVIEW.C
  4. *
  5. ****************************************************************************/
  6. #include <windows.h>
  7. #include <mmsystem.h>
  8. #include <commdlg.h>
  9. #include <win32.h>
  10. #include <vfw.h>
  11. #define SQUAWKNUMZ(num) #num
  12. #define SQUAWKNUM(num) SQUAWKNUMZ(num)
  13. #define SQUAWK __FILE__ "(" SQUAWKNUM(__LINE__) ") :squawk: "
  14. typedef struct {
  15. BOOL bUnicode;
  16. HWND hwnd; // common dialog handle.
  17. LPOPENFILENAME pofn;
  18. LPARAM lCustData; // hold old value
  19. DWORD Flags;
  20. LPOFNHOOKPROC lpfnHook;
  21. RECT rcPreview;
  22. RECT rcImage;
  23. RECT rcText;
  24. HWND hwndMci;
  25. HFONT hfont;
  26. HPALETTE hpal;
  27. HANDLE hdib;
  28. TCHAR Title[128];
  29. } PreviewStuff, FAR *PPreviewStuff;
  30. #define PREVIEW_PROP TEXT("PreviewStuff")
  31. #ifdef _WIN32
  32. #define SetPreviewStuff(hwnd, p) SetProp(hwnd,PREVIEW_PROP,(LPVOID)(p))
  33. #define GetPreviewStuff(hwnd) (PPreviewStuff)(LPVOID)GetProp(hwnd, PREVIEW_PROP)
  34. #define RemovePreviewStuff(hwnd) RemoveProp(hwnd,PREVIEW_PROP)
  35. #else
  36. #define SetPreviewStuff(hwnd, p) SetProp(hwnd,PREVIEW_PROP,HIWORD(p))
  37. #define GetPreviewStuff(hwnd) (PPreviewStuff)MAKELONG(0, GetProp(hwnd, PREVIEW_PROP))
  38. #define RemovePreviewStuff(hwnd) RemoveProp(hwnd,PREVIEW_PROP)
  39. #define CharNext AnsiNext
  40. #define CharPrev AnsiPrev
  41. #define CharUpperBuff AnsiUpperBuff
  42. #define CharLower AnsiLower
  43. #endif
  44. /***************************************************************************
  45. *
  46. ****************************************************************************/
  47. STATICFN BOOL PreviewOpen (HWND hwnd, LPOPENFILENAME pofn);
  48. STATICFN BOOL PreviewFile (PPreviewStuff p, LPTSTR szFile);
  49. STATICFN BOOL PreviewPaint(PPreviewStuff p);
  50. STATICFN BOOL PreviewSize (PPreviewStuff p);
  51. STATICFN BOOL PreviewClose(PPreviewStuff p);
  52. STATICFN HANDLE GetRiffDisp(LPTSTR lpszFile, LPTSTR szText, int iLen);
  53. /***************************************************************************
  54. *
  55. ****************************************************************************/
  56. STATICFN BOOL PreviewOpen(HWND hwnd, LPOPENFILENAME pofn)
  57. {
  58. LOGFONT lf;
  59. PPreviewStuff p;
  60. RECT rc;
  61. p = (LPVOID)pofn->lCustData;
  62. pofn->lCustData = p->lCustData;
  63. SetPreviewStuff(hwnd, p);
  64. p->hwnd = hwnd;
  65. p->pofn = pofn;
  66. //
  67. // create a MCI window for preview.
  68. //
  69. p->hwndMci = MCIWndCreate(p->hwnd, NULL,
  70. // MCIWNDF_NOAUTOSIZEWINDOW |
  71. // MCIWNDF_NOPLAYBAR |
  72. // MCIWNDF_NOAUTOSIZEMOVIE |
  73. MCIWNDF_NOMENU |
  74. // MCIWNDF_SHOWNAME |
  75. // MCIWNDF_SHOWPOS |
  76. // MCIWNDF_SHOWMODE |
  77. // MCIWNDF_RECORD |
  78. MCIWNDF_NOERRORDLG |
  79. WS_CHILD | WS_BORDER,
  80. NULL);
  81. //
  82. // locate the preview in the lower corner of the dialog (below the
  83. // cancel button)
  84. //
  85. GetClientRect(hwnd, &p->rcPreview);
  86. GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rc);
  87. ScreenToClient(hwnd, (LPPOINT)&rc);
  88. ScreenToClient(hwnd, (LPPOINT)&rc+1);
  89. // The open space we're allowed to use in the dialog is different in NT and on
  90. // Win31. Under NT there is a network button at the bottom of the dialog on
  91. // the right hand side, so we use the area from just under the CANCEL button to
  92. // a little more than 1 button height from the bottom of the dialog.
  93. // Under Win31, the network button is under CANCEL, so we use the area a little
  94. // over one button height under CANCEL, to just about the bottom of the dialog.
  95. #ifdef _WIN32
  96. if (1)
  97. #else
  98. if (GetWinFlags() & WF_WINNT)
  99. #endif
  100. {
  101. p->rcPreview.top = rc.bottom + 4;
  102. p->rcPreview.left = rc.left;
  103. p->rcPreview.right = rc.right;
  104. p->rcPreview.bottom -= (rc.bottom - rc.top) + 12;
  105. } else {
  106. p->rcPreview.top = rc.bottom + (rc.bottom - rc.top) + 12;
  107. p->rcPreview.left = rc.left;
  108. p->rcPreview.right = rc.right;
  109. p->rcPreview.bottom -= 4; // leave a little room at the bottom
  110. }
  111. //
  112. // create a font to use.
  113. //
  114. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (LPVOID)&lf, 0);
  115. p->hfont = CreateFontIndirect(&lf);
  116. return TRUE;
  117. }
  118. /***************************************************************************
  119. *
  120. ****************************************************************************/
  121. STATICFN BOOL PreviewClose(PPreviewStuff p)
  122. {
  123. if (p == NULL)
  124. return FALSE;
  125. PreviewFile(p, NULL);
  126. RemovePreviewStuff(p->hwnd);
  127. if (p->hfont)
  128. {
  129. DeleteObject(p->hfont);
  130. p->hfont = NULL ;
  131. }
  132. if (p->hwndMci)
  133. {
  134. MCIWndDestroy(p->hwndMci);
  135. p->hwndMci = NULL ;
  136. }
  137. return TRUE;
  138. }
  139. /***************************************************************************
  140. *
  141. ****************************************************************************/
  142. #define SLASH(c) ((c) == TEXT('/') || (c) == TEXT('\\'))
  143. STATICFN LPTSTR NiceName(LPTSTR szPath)
  144. {
  145. LPTSTR sz;
  146. LPTSTR lpsztmp;
  147. for (sz=szPath; *sz; sz++)
  148. ;
  149. for (; sz>szPath && !SLASH(*sz) && *sz!=TEXT(':'); sz =CharPrev(szPath, sz))
  150. ;
  151. if(sz>szPath) sz = CharNext(sz) ;
  152. for(lpsztmp = sz; *lpsztmp && *lpsztmp != TEXT('.'); lpsztmp = CharNext(lpsztmp))
  153. ;
  154. *lpsztmp = TEXT('\0');
  155. CharLower(sz);
  156. CharUpperBuff(sz, 1);
  157. return sz;
  158. }
  159. /***************************************************************************
  160. *
  161. ****************************************************************************/
  162. STATICFN BOOL PreviewFile(PPreviewStuff p, LPTSTR szFile)
  163. {
  164. if (p == NULL || !p->hwndMci)
  165. return FALSE;
  166. p->Title[0] = 0;
  167. ShowWindow(p->hwndMci, SW_HIDE);
  168. MCIWndClose(p->hwndMci);
  169. if (p->hdib)
  170. GlobalFree(p->hdib);
  171. if (p->hpal)
  172. DeleteObject(p->hpal);
  173. p->hdib = NULL;
  174. p->hpal = NULL;
  175. PreviewPaint(p);
  176. if (szFile == NULL)
  177. return TRUE;
  178. if (MCIWndOpen(p->hwndMci, szFile, 0) == 0)
  179. {
  180. lstrcpy(p->Title, NiceName(szFile));
  181. if (MCIWndUseTime(p->hwndMci) == 0)
  182. {
  183. LONG len;
  184. UINT min,sec;
  185. len = MCIWndGetLength(p->hwndMci);
  186. if (len > 0)
  187. {
  188. #define ONE_HOUR (60ul*60ul*1000ul)
  189. #define ONE_MINUTE (60ul*1000ul)
  190. #define ONE_SECOND (1000ul)
  191. min = (UINT)(len / ONE_MINUTE) % 60;
  192. sec = (UINT)(len / ONE_SECOND) % 60;
  193. wsprintf(p->Title + lstrlen(p->Title), TEXT(" (%02d:%02d)"), min, sec);
  194. }
  195. }
  196. }
  197. PreviewSize(p);
  198. PreviewPaint(p);
  199. return TRUE;
  200. }
  201. /***************************************************************************
  202. *
  203. ****************************************************************************/
  204. STATICFN BOOL PreviewSize(PPreviewStuff p)
  205. {
  206. RECT rc;
  207. RECT rcImage;
  208. RECT rcText;
  209. RECT rcPreview;
  210. HDC hdc;
  211. int dx;
  212. int dy;
  213. int dyPlayBar;
  214. SetRectEmpty(&p->rcText);
  215. SetRectEmpty(&p->rcImage);
  216. //
  217. // if nothing to do clear it.
  218. //
  219. if (p->Title[0] == 0 && p->hdib == NULL)
  220. return FALSE;
  221. rcPreview = p->rcPreview;
  222. //
  223. // compute the text rect, using DrawText
  224. //
  225. hdc = GetDC(p->hwnd);
  226. SelectObject(hdc, p->hfont);
  227. rcText = rcPreview;
  228. rcText.bottom = rcText.top;
  229. DrawText(hdc, p->Title, -1, &rcText, DT_CALCRECT|DT_LEFT|DT_WORDBREAK);
  230. ReleaseDC(p->hwnd, hdc);
  231. //
  232. // compute the image size
  233. //
  234. MCIWndChangeStyles(p->hwndMci, MCIWNDF_NOPLAYBAR, MCIWNDF_NOPLAYBAR);
  235. GetWindowRect(p->hwndMci, &rc);
  236. dx = rc.right - rc.left;
  237. dy = rc.bottom - rc.top;
  238. MCIWndChangeStyles(p->hwndMci, MCIWNDF_NOPLAYBAR, 0);
  239. GetWindowRect(p->hwndMci, &rc);
  240. dyPlayBar = rc.bottom - rc.top - dy;
  241. rcImage = rcPreview;
  242. rcImage.bottom -= dyPlayBar;
  243. //
  244. // if wider than preview area scale to fit
  245. //
  246. if (dx > rcImage.right - rcImage.left)
  247. {
  248. rcImage.bottom = rcImage.top + MulDiv(dy,rcImage.right-rcImage.left,dx);
  249. }
  250. //
  251. // if x2 will fit then use it
  252. //
  253. else if (dx * 2 < rcImage.right - rcImage.left)
  254. {
  255. rcImage.right = rcImage.left + dx*2;
  256. rcImage.bottom = rcImage.top + dy*2;
  257. }
  258. //
  259. // else center the image in the preview area
  260. //
  261. else
  262. {
  263. rcImage.right = rcImage.left + dx;
  264. rcImage.bottom = rcImage.top + dy;
  265. }
  266. if (rcImage.bottom > rcPreview.bottom - (rcText.bottom - rcText.top) - dyPlayBar)
  267. {
  268. rcImage.bottom = rcPreview.bottom - (rcText.bottom - rcText.top) - dyPlayBar;
  269. rcImage.right = rcPreview.left + MulDiv(dx,rcImage.bottom-rcImage.top,dy);
  270. rcImage.left = rcPreview.left;
  271. }
  272. rcImage.bottom += dyPlayBar;
  273. //
  274. // now center
  275. //
  276. dx = ((rcPreview.right - rcPreview.left) - (rcText.right - rcText.left))/2;
  277. OffsetRect(&rcText, dx, 0);
  278. dx = ((rcPreview.right - rcPreview.left) - (rcImage.right - rcImage.left))/2;
  279. OffsetRect(&rcImage, dx, 0);
  280. dy = rcPreview.bottom - rcPreview.top;
  281. dy -= rcImage.bottom - rcImage.top;
  282. dy -= rcText.bottom - rcText.top;
  283. if (dy < 0)
  284. dy = 0;
  285. else
  286. dy = dy / 2;
  287. OffsetRect(&rcImage, 0, dy);
  288. OffsetRect(&rcText, 0, dy + rcImage.bottom - rcImage.top + 2);
  289. //
  290. // store RECTs
  291. //
  292. p->rcImage = rcImage;
  293. p->rcText = rcText;
  294. //
  295. // position window.
  296. //
  297. SetWindowPos(p->hwndMci, NULL, rcImage.left, rcImage.top,
  298. rcImage.right - rcImage.left, rcImage.bottom - rcImage.top,
  299. SWP_NOZORDER | SWP_NOACTIVATE);
  300. ShowWindow(p->hwndMci, SW_SHOW);
  301. return TRUE;
  302. }
  303. /***************************************************************************
  304. *
  305. ****************************************************************************/
  306. STATICFN BOOL PreviewPaint(PPreviewStuff p)
  307. {
  308. HDC hdc;
  309. HBRUSH hbr;
  310. HWND hwnd = p->hwnd;
  311. if (p == NULL)
  312. return TRUE;
  313. hdc = GetDC(hwnd);
  314. #ifdef _WIN32
  315. hbr = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hwnd);
  316. #else
  317. hbr = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLOR, (WPARAM)hdc, MAKELONG(hwnd, CTLCOLOR_DLG));
  318. #endif
  319. ////FillRect(hdc, &p->rcPreview, hbr);
  320. FillRect(hdc, &p->rcText, hbr);
  321. SelectObject(hdc, p->hfont);
  322. DrawText(hdc, p->Title, -1, &p->rcText, DT_LEFT|DT_WORDBREAK);
  323. ReleaseDC(hwnd, hdc);
  324. return TRUE;
  325. }
  326. /***************************************************************************
  327. *
  328. ****************************************************************************/
  329. #pragma message (SQUAWK "should use the correct header for cmb1, etc")
  330. /* Combo boxes */
  331. #define cmb1 0x0470
  332. #define cmb2 0x0471
  333. /* Listboxes */
  334. #define lst1 0x0460
  335. #define lst2 0x0461
  336. /* Edit controls */
  337. #define edt1 0x0480
  338. #define ID_TIMER 1234
  339. #define PREVIEWWAIT 1000
  340. UINT_PTR FAR PASCAL _loadds GetFileNamePreviewHook(HWND hwnd, unsigned msg, WPARAM wParam, LPARAM lParam)
  341. {
  342. int i;
  343. TCHAR ach[80];
  344. PPreviewStuff p;
  345. p = GetPreviewStuff(hwnd);
  346. switch (msg) {
  347. case WM_COMMAND:
  348. switch (GET_WM_COMMAND_ID(wParam, lParam))
  349. {
  350. case lst1:
  351. if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE)
  352. {
  353. KillTimer(hwnd, ID_TIMER);
  354. SetTimer(hwnd, ID_TIMER, PREVIEWWAIT, NULL);
  355. }
  356. break;
  357. case IDOK:
  358. case IDCANCEL:
  359. KillTimer(hwnd, ID_TIMER);
  360. PreviewFile(p, NULL);
  361. break;
  362. case cmb1:
  363. case cmb2:
  364. case lst2:
  365. if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE)
  366. {
  367. KillTimer(hwnd, ID_TIMER);
  368. PreviewFile(p, NULL);
  369. }
  370. break;
  371. }
  372. break;
  373. case WM_TIMER:
  374. if (wParam == ID_TIMER)
  375. {
  376. KillTimer(hwnd, ID_TIMER);
  377. ach[0] = 0;
  378. i = (int)SendDlgItemMessage(hwnd, lst1, LB_GETCURSEL, 0, 0L);
  379. SendDlgItemMessage(hwnd, lst1, LB_GETTEXT, i, (LPARAM)(LPTSTR)ach);
  380. PreviewFile(p, ach);
  381. return TRUE;
  382. }
  383. break;
  384. case WM_QUERYNEWPALETTE:
  385. case WM_PALETTECHANGED:
  386. if (p && p->hwndMci)
  387. SendMessage(p->hwndMci, msg, wParam, lParam);
  388. break;
  389. case WM_PAINT:
  390. PreviewPaint(p);
  391. break;
  392. case WM_INITDIALOG:
  393. PreviewOpen(hwnd, (LPOPENFILENAME)lParam);
  394. p = GetPreviewStuff(hwnd);
  395. if (!(p->Flags & OFN_ENABLEHOOK))
  396. return TRUE;
  397. break;
  398. case WM_DESTROY:
  399. PreviewClose(p);
  400. break;
  401. }
  402. if (p && (p->Flags & OFN_ENABLEHOOK))
  403. return (int)p->lpfnHook(hwnd, msg, wParam, lParam);
  404. else
  405. return FALSE;
  406. }
  407. /***************************************************************************
  408. *
  409. ****************************************************************************/
  410. STATICFN BOOL GetFileNamePreview(LPOPENFILENAME lpofn, BOOL fSave, BOOL bUnicode)
  411. {
  412. BOOL f;
  413. PPreviewStuff p;
  414. //////// Link to COMMDLG
  415. HINSTANCE h;
  416. BOOL (WINAPI *GetFileNameProc)(OPENFILENAME FAR*) = NULL;
  417. char procname[60];
  418. if (fSave) {
  419. lstrcpyA(procname, "GetSaveFileName");
  420. } else {
  421. lstrcpyA(procname, "GetOpenFileName");
  422. }
  423. #ifdef _WIN32
  424. if (bUnicode) {
  425. lstrcatA(procname, "W");
  426. } else {
  427. lstrcatA(procname, "A");
  428. }
  429. #endif
  430. #ifdef _WIN32
  431. if ((h = LoadLibrary(TEXT("COMDLG32.DLL"))) != NULL) {
  432. (FARPROC)GetFileNameProc = GetProcAddress(h, procname);
  433. #else
  434. if ((h = LoadLibrary(TEXT("COMMDLG.DLL"))) >= (HINSTANCE)HINSTANCE_ERROR) {
  435. (FARPROC)GetFileNameProc = GetProcAddress(h, procname);
  436. #endif
  437. }
  438. if (GetFileNameProc == NULL)
  439. return FALSE; //!!! what's the right error here?
  440. ////////////////
  441. #ifndef OFN_NONETWORKBUTTON
  442. #define OFN_NONETWORKBUTTON 0x00020000
  443. #endif
  444. // If we have a READ ONLY checkbox, or both HELP and NETWORK, then it's in
  445. // our way, so get rid of it. (keep NETWORK, lose HELP)
  446. if (!(lpofn->Flags & OFN_HIDEREADONLY))
  447. lpofn->Flags |= OFN_HIDEREADONLY;
  448. if ((lpofn->Flags & OFN_SHOWHELP) && !(lpofn->Flags & OFN_NONETWORKBUTTON))
  449. lpofn->Flags &= ~OFN_SHOWHELP;
  450. p = (LPVOID)GlobalAllocPtr(GHND, sizeof(PreviewStuff));
  451. if (p == NULL)
  452. {
  453. f = GetFileNameProc(lpofn);
  454. }
  455. else
  456. {
  457. p->bUnicode = bUnicode;
  458. p->lpfnHook = lpofn->lpfnHook;
  459. p->Flags = lpofn->Flags;
  460. p->lCustData = lpofn->lCustData;
  461. lpofn->lpfnHook = (LPVOID)GetFileNamePreviewHook;
  462. lpofn->Flags |= OFN_ENABLEHOOK;
  463. lpofn->lCustData = (LPARAM)p;
  464. f = GetFileNameProc(lpofn);
  465. lpofn->lpfnHook = p->lpfnHook;
  466. lpofn->Flags = p->Flags;
  467. GlobalFreePtr(p);
  468. }
  469. FreeLibrary(h); //!!! should we free DLL?
  470. return f;
  471. }
  472. #ifdef _WIN32
  473. /**************************************************************************
  474. * @doc EXTERNAL
  475. *
  476. * @api BOOL | GetOpenFileNamePreview | This is just like <f GetOpenFileName>
  477. * in COMMDLG, but with a preview window so people can see what movie
  478. * they're opening.
  479. *
  480. * @parm LPOPENFILENAME | lpofn | See the documentation for <f GetOpenFileName>.
  481. *
  482. * @rdesc Returns true if a file was opened.
  483. *
  484. * @xref GetOpenFileName
  485. *
  486. *************************************************************************/
  487. BOOL FAR PASCAL _loadds GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn)
  488. {
  489. return GetFileNamePreview((LPOPENFILENAME)lpofn, FALSE, TRUE);
  490. }
  491. /**************************************************************************
  492. * @doc EXTERNAL
  493. *
  494. * @api BOOL | GetSaveFileNamePreview | This is just like <f GetSaveFileName>
  495. * in COMMDLG, but with a preview window so people can see what movie
  496. * they're saving over.
  497. *
  498. * @parm LPOPENFILENAME | lpofn | See the documentation for <f GetSaveFileName>.
  499. *
  500. * @rdesc Returns true if a file was opened.
  501. *
  502. * @xref GetSaveFileName
  503. *
  504. *************************************************************************/
  505. BOOL FAR PASCAL _loadds GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn)
  506. {
  507. return GetFileNamePreview((LPOPENFILENAME)lpofn, TRUE, TRUE);
  508. }
  509. // ansi thunks for above two functions
  510. BOOL FAR PASCAL _loadds GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn)
  511. {
  512. return GetFileNamePreview((LPOPENFILENAME)lpofn, FALSE, FALSE);
  513. }
  514. BOOL FAR PASCAL _loadds GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn)
  515. {
  516. return GetFileNamePreview((LPOPENFILENAME)lpofn, TRUE, FALSE);
  517. }
  518. #else
  519. BOOL FAR PASCAL _loadds GetOpenFileNamePreview(LPOPENFILENAME lpofn)
  520. {
  521. return GetFileNamePreview(lpofn, FALSE, FALSE);
  522. }
  523. BOOL FAR PASCAL _loadds GetSaveFileNamePreview(LPOPENFILENAME lpofn)
  524. {
  525. return GetFileNamePreview(lpofn, TRUE, FALSE);
  526. }
  527. #endif