|
|
/****************************************************************************
* * MODULE : PREVIEW.C * ****************************************************************************/
#include <windows.h>
#include <mmsystem.h>
#include <commdlg.h>
#include <win32.h>
#include <vfw.h>
#define SQUAWKNUMZ(num) #num
#define SQUAWKNUM(num) SQUAWKNUMZ(num)
#define SQUAWK __FILE__ "(" SQUAWKNUM(__LINE__) ") :squawk: "
typedef struct { BOOL bUnicode; HWND hwnd; // common dialog handle.
LPOPENFILENAME pofn;
LPARAM lCustData; // hold old value
DWORD Flags; LPOFNHOOKPROC lpfnHook;
RECT rcPreview; RECT rcImage; RECT rcText; HWND hwndMci; HFONT hfont; HPALETTE hpal; HANDLE hdib; TCHAR Title[128];
} PreviewStuff, FAR *PPreviewStuff;
#define PREVIEW_PROP TEXT("PreviewStuff")
#ifdef _WIN32
#define SetPreviewStuff(hwnd, p) SetProp(hwnd,PREVIEW_PROP,(LPVOID)(p))
#define GetPreviewStuff(hwnd) (PPreviewStuff)(LPVOID)GetProp(hwnd, PREVIEW_PROP)
#define RemovePreviewStuff(hwnd) RemoveProp(hwnd,PREVIEW_PROP)
#else
#define SetPreviewStuff(hwnd, p) SetProp(hwnd,PREVIEW_PROP,HIWORD(p))
#define GetPreviewStuff(hwnd) (PPreviewStuff)MAKELONG(0, GetProp(hwnd, PREVIEW_PROP))
#define RemovePreviewStuff(hwnd) RemoveProp(hwnd,PREVIEW_PROP)
#define CharNext AnsiNext
#define CharPrev AnsiPrev
#define CharUpperBuff AnsiUpperBuff
#define CharLower AnsiLower
#endif
/***************************************************************************
* ****************************************************************************/
STATICFN BOOL PreviewOpen (HWND hwnd, LPOPENFILENAME pofn); STATICFN BOOL PreviewFile (PPreviewStuff p, LPTSTR szFile); STATICFN BOOL PreviewPaint(PPreviewStuff p); STATICFN BOOL PreviewSize (PPreviewStuff p); STATICFN BOOL PreviewClose(PPreviewStuff p);
STATICFN HANDLE GetRiffDisp(LPTSTR lpszFile, LPTSTR szText, int iLen);
/***************************************************************************
* ****************************************************************************/
STATICFN BOOL PreviewOpen(HWND hwnd, LPOPENFILENAME pofn) { LOGFONT lf; PPreviewStuff p; RECT rc;
p = (LPVOID)pofn->lCustData; pofn->lCustData = p->lCustData;
SetPreviewStuff(hwnd, p);
p->hwnd = hwnd; p->pofn = pofn;
//
// create a MCI window for preview.
//
p->hwndMci = MCIWndCreate(p->hwnd, NULL, // MCIWNDF_NOAUTOSIZEWINDOW |
// MCIWNDF_NOPLAYBAR |
// MCIWNDF_NOAUTOSIZEMOVIE |
MCIWNDF_NOMENU | // MCIWNDF_SHOWNAME |
// MCIWNDF_SHOWPOS |
// MCIWNDF_SHOWMODE |
// MCIWNDF_RECORD |
MCIWNDF_NOERRORDLG | WS_CHILD | WS_BORDER, NULL);
//
// locate the preview in the lower corner of the dialog (below the
// cancel button)
//
GetClientRect(hwnd, &p->rcPreview); GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rc); ScreenToClient(hwnd, (LPPOINT)&rc); ScreenToClient(hwnd, (LPPOINT)&rc+1);
// The open space we're allowed to use in the dialog is different in NT and on
// Win31. Under NT there is a network button at the bottom of the dialog on
// the right hand side, so we use the area from just under the CANCEL button to
// a little more than 1 button height from the bottom of the dialog.
// Under Win31, the network button is under CANCEL, so we use the area a little
// over one button height under CANCEL, to just about the bottom of the dialog.
#ifdef _WIN32
if (1) #else
if (GetWinFlags() & WF_WINNT) #endif
{ p->rcPreview.top = rc.bottom + 4; p->rcPreview.left = rc.left; p->rcPreview.right = rc.right; p->rcPreview.bottom -= (rc.bottom - rc.top) + 12; } else { p->rcPreview.top = rc.bottom + (rc.bottom - rc.top) + 12; p->rcPreview.left = rc.left; p->rcPreview.right = rc.right; p->rcPreview.bottom -= 4; // leave a little room at the bottom
}
//
// create a font to use.
//
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (LPVOID)&lf, 0); p->hfont = CreateFontIndirect(&lf);
return TRUE; }
/***************************************************************************
* ****************************************************************************/
STATICFN BOOL PreviewClose(PPreviewStuff p) { if (p == NULL) return FALSE;
PreviewFile(p, NULL);
RemovePreviewStuff(p->hwnd);
if (p->hfont) { DeleteObject(p->hfont); p->hfont = NULL ; }
if (p->hwndMci) { MCIWndDestroy(p->hwndMci); p->hwndMci = NULL ; }
return TRUE; }
/***************************************************************************
* ****************************************************************************/
#define SLASH(c) ((c) == TEXT('/') || (c) == TEXT('\\'))
STATICFN LPTSTR NiceName(LPTSTR szPath) { LPTSTR sz; LPTSTR lpsztmp;
for (sz=szPath; *sz; sz++) ; for (; sz>szPath && !SLASH(*sz) && *sz!=TEXT(':'); sz =CharPrev(szPath, sz)) ; if(sz>szPath) sz = CharNext(sz) ;
for(lpsztmp = sz; *lpsztmp && *lpsztmp != TEXT('.'); lpsztmp = CharNext(lpsztmp)) ; *lpsztmp = TEXT('\0');
CharLower(sz); CharUpperBuff(sz, 1);
return sz; }
/***************************************************************************
* ****************************************************************************/
STATICFN BOOL PreviewFile(PPreviewStuff p, LPTSTR szFile) { if (p == NULL || !p->hwndMci) return FALSE;
p->Title[0] = 0;
ShowWindow(p->hwndMci, SW_HIDE); MCIWndClose(p->hwndMci);
if (p->hdib) GlobalFree(p->hdib);
if (p->hpal) DeleteObject(p->hpal);
p->hdib = NULL; p->hpal = NULL;
PreviewPaint(p);
if (szFile == NULL) return TRUE;
if (MCIWndOpen(p->hwndMci, szFile, 0) == 0) { lstrcpy(p->Title, NiceName(szFile));
if (MCIWndUseTime(p->hwndMci) == 0) { LONG len; UINT min,sec;
len = MCIWndGetLength(p->hwndMci);
if (len > 0) { #define ONE_HOUR (60ul*60ul*1000ul)
#define ONE_MINUTE (60ul*1000ul)
#define ONE_SECOND (1000ul)
min = (UINT)(len / ONE_MINUTE) % 60; sec = (UINT)(len / ONE_SECOND) % 60;
wsprintf(p->Title + lstrlen(p->Title), TEXT(" (%02d:%02d)"), min, sec); } } }
PreviewSize(p); PreviewPaint(p); return TRUE; }
/***************************************************************************
* ****************************************************************************/
STATICFN BOOL PreviewSize(PPreviewStuff p) { RECT rc; RECT rcImage; RECT rcText; RECT rcPreview; HDC hdc; int dx; int dy; int dyPlayBar;
SetRectEmpty(&p->rcText); SetRectEmpty(&p->rcImage);
//
// if nothing to do clear it.
//
if (p->Title[0] == 0 && p->hdib == NULL) return FALSE;
rcPreview = p->rcPreview;
//
// compute the text rect, using DrawText
//
hdc = GetDC(p->hwnd); SelectObject(hdc, p->hfont);
rcText = rcPreview; rcText.bottom = rcText.top;
DrawText(hdc, p->Title, -1, &rcText, DT_CALCRECT|DT_LEFT|DT_WORDBREAK); ReleaseDC(p->hwnd, hdc);
//
// compute the image size
//
MCIWndChangeStyles(p->hwndMci, MCIWNDF_NOPLAYBAR, MCIWNDF_NOPLAYBAR); GetWindowRect(p->hwndMci, &rc); dx = rc.right - rc.left; dy = rc.bottom - rc.top; MCIWndChangeStyles(p->hwndMci, MCIWNDF_NOPLAYBAR, 0); GetWindowRect(p->hwndMci, &rc); dyPlayBar = rc.bottom - rc.top - dy;
rcImage = rcPreview; rcImage.bottom -= dyPlayBar;
//
// if wider than preview area scale to fit
//
if (dx > rcImage.right - rcImage.left) { rcImage.bottom = rcImage.top + MulDiv(dy,rcImage.right-rcImage.left,dx); } //
// if x2 will fit then use it
//
else if (dx * 2 < rcImage.right - rcImage.left) { rcImage.right = rcImage.left + dx*2; rcImage.bottom = rcImage.top + dy*2; } //
// else center the image in the preview area
//
else { rcImage.right = rcImage.left + dx; rcImage.bottom = rcImage.top + dy; }
if (rcImage.bottom > rcPreview.bottom - (rcText.bottom - rcText.top) - dyPlayBar) { rcImage.bottom = rcPreview.bottom - (rcText.bottom - rcText.top) - dyPlayBar; rcImage.right = rcPreview.left + MulDiv(dx,rcImage.bottom-rcImage.top,dy); rcImage.left = rcPreview.left; }
rcImage.bottom += dyPlayBar;
//
// now center
//
dx = ((rcPreview.right - rcPreview.left) - (rcText.right - rcText.left))/2; OffsetRect(&rcText, dx, 0);
dx = ((rcPreview.right - rcPreview.left) - (rcImage.right - rcImage.left))/2; OffsetRect(&rcImage, dx, 0);
dy = rcPreview.bottom - rcPreview.top; dy -= rcImage.bottom - rcImage.top; dy -= rcText.bottom - rcText.top;
if (dy < 0) dy = 0; else dy = dy / 2;
OffsetRect(&rcImage, 0, dy); OffsetRect(&rcText, 0, dy + rcImage.bottom - rcImage.top + 2);
//
// store RECTs
//
p->rcImage = rcImage; p->rcText = rcText;
//
// position window.
//
SetWindowPos(p->hwndMci, NULL, rcImage.left, rcImage.top, rcImage.right - rcImage.left, rcImage.bottom - rcImage.top, SWP_NOZORDER | SWP_NOACTIVATE);
ShowWindow(p->hwndMci, SW_SHOW);
return TRUE; }
/***************************************************************************
* ****************************************************************************/
STATICFN BOOL PreviewPaint(PPreviewStuff p) { HDC hdc; HBRUSH hbr; HWND hwnd = p->hwnd;
if (p == NULL) return TRUE;
hdc = GetDC(hwnd);
#ifdef _WIN32
hbr = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hwnd); #else
hbr = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLOR, (WPARAM)hdc, MAKELONG(hwnd, CTLCOLOR_DLG)); #endif
////FillRect(hdc, &p->rcPreview, hbr);
FillRect(hdc, &p->rcText, hbr);
SelectObject(hdc, p->hfont); DrawText(hdc, p->Title, -1, &p->rcText, DT_LEFT|DT_WORDBREAK);
ReleaseDC(hwnd, hdc); return TRUE; }
/***************************************************************************
* ****************************************************************************/
#pragma message (SQUAWK "should use the correct header for cmb1, etc")
/* Combo boxes */ #define cmb1 0x0470
#define cmb2 0x0471
/* Listboxes */ #define lst1 0x0460
#define lst2 0x0461
/* Edit controls */ #define edt1 0x0480
#define ID_TIMER 1234
#define PREVIEWWAIT 1000
UINT_PTR FAR PASCAL _loadds GetFileNamePreviewHook(HWND hwnd, unsigned msg, WPARAM wParam, LPARAM lParam) { int i; TCHAR ach[80];
PPreviewStuff p;
p = GetPreviewStuff(hwnd);
switch (msg) { case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case lst1: if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) { KillTimer(hwnd, ID_TIMER); SetTimer(hwnd, ID_TIMER, PREVIEWWAIT, NULL); } break;
case IDOK: case IDCANCEL: KillTimer(hwnd, ID_TIMER); PreviewFile(p, NULL); break;
case cmb1: case cmb2: case lst2: if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) { KillTimer(hwnd, ID_TIMER); PreviewFile(p, NULL); } break; } break;
case WM_TIMER: if (wParam == ID_TIMER) { KillTimer(hwnd, ID_TIMER);
ach[0] = 0; i = (int)SendDlgItemMessage(hwnd, lst1, LB_GETCURSEL, 0, 0L); SendDlgItemMessage(hwnd, lst1, LB_GETTEXT, i, (LPARAM)(LPTSTR)ach); PreviewFile(p, ach); return TRUE; } break;
case WM_QUERYNEWPALETTE: case WM_PALETTECHANGED: if (p && p->hwndMci) SendMessage(p->hwndMci, msg, wParam, lParam); break;
case WM_PAINT: PreviewPaint(p); break;
case WM_INITDIALOG: PreviewOpen(hwnd, (LPOPENFILENAME)lParam);
p = GetPreviewStuff(hwnd);
if (!(p->Flags & OFN_ENABLEHOOK)) return TRUE;
break;
case WM_DESTROY: PreviewClose(p); break; }
if (p && (p->Flags & OFN_ENABLEHOOK)) return (int)p->lpfnHook(hwnd, msg, wParam, lParam); else return FALSE; }
/***************************************************************************
* ****************************************************************************/
STATICFN BOOL GetFileNamePreview(LPOPENFILENAME lpofn, BOOL fSave, BOOL bUnicode) { BOOL f; PPreviewStuff p;
//////// Link to COMMDLG
HINSTANCE h; BOOL (WINAPI *GetFileNameProc)(OPENFILENAME FAR*) = NULL; char procname[60];
if (fSave) { lstrcpyA(procname, "GetSaveFileName"); } else { lstrcpyA(procname, "GetOpenFileName"); } #ifdef _WIN32
if (bUnicode) { lstrcatA(procname, "W"); } else { lstrcatA(procname, "A"); } #endif
#ifdef _WIN32
if ((h = LoadLibrary(TEXT("COMDLG32.DLL"))) != NULL) { (FARPROC)GetFileNameProc = GetProcAddress(h, procname); #else
if ((h = LoadLibrary(TEXT("COMMDLG.DLL"))) >= (HINSTANCE)HINSTANCE_ERROR) { (FARPROC)GetFileNameProc = GetProcAddress(h, procname); #endif
}
if (GetFileNameProc == NULL) return FALSE; //!!! what's the right error here?
////////////////
#ifndef OFN_NONETWORKBUTTON
#define OFN_NONETWORKBUTTON 0x00020000
#endif
// If we have a READ ONLY checkbox, or both HELP and NETWORK, then it's in
// our way, so get rid of it. (keep NETWORK, lose HELP)
if (!(lpofn->Flags & OFN_HIDEREADONLY)) lpofn->Flags |= OFN_HIDEREADONLY; if ((lpofn->Flags & OFN_SHOWHELP) && !(lpofn->Flags & OFN_NONETWORKBUTTON)) lpofn->Flags &= ~OFN_SHOWHELP;
p = (LPVOID)GlobalAllocPtr(GHND, sizeof(PreviewStuff));
if (p == NULL) { f = GetFileNameProc(lpofn); } else { p->bUnicode = bUnicode; p->lpfnHook = lpofn->lpfnHook; p->Flags = lpofn->Flags; p->lCustData = lpofn->lCustData;
lpofn->lpfnHook = (LPVOID)GetFileNamePreviewHook; lpofn->Flags |= OFN_ENABLEHOOK; lpofn->lCustData = (LPARAM)p;
f = GetFileNameProc(lpofn);
lpofn->lpfnHook = p->lpfnHook; lpofn->Flags = p->Flags;
GlobalFreePtr(p); }
FreeLibrary(h); //!!! should we free DLL?
return f; }
#ifdef _WIN32
/**************************************************************************
* @doc EXTERNAL * * @api BOOL | GetOpenFileNamePreview | This is just like <f GetOpenFileName> * in COMMDLG, but with a preview window so people can see what movie * they're opening. * * @parm LPOPENFILENAME | lpofn | See the documentation for <f GetOpenFileName>. * * @rdesc Returns true if a file was opened. * * @xref GetOpenFileName * *************************************************************************/ BOOL FAR PASCAL _loadds GetOpenFileNamePreviewW(LPOPENFILENAMEW lpofn) { return GetFileNamePreview((LPOPENFILENAME)lpofn, FALSE, TRUE); }
/**************************************************************************
* @doc EXTERNAL * * @api BOOL | GetSaveFileNamePreview | This is just like <f GetSaveFileName> * in COMMDLG, but with a preview window so people can see what movie * they're saving over. * * @parm LPOPENFILENAME | lpofn | See the documentation for <f GetSaveFileName>. * * @rdesc Returns true if a file was opened. * * @xref GetSaveFileName * *************************************************************************/ BOOL FAR PASCAL _loadds GetSaveFileNamePreviewW(LPOPENFILENAMEW lpofn) { return GetFileNamePreview((LPOPENFILENAME)lpofn, TRUE, TRUE); }
// ansi thunks for above two functions
BOOL FAR PASCAL _loadds GetOpenFileNamePreviewA(LPOPENFILENAMEA lpofn) { return GetFileNamePreview((LPOPENFILENAME)lpofn, FALSE, FALSE); }
BOOL FAR PASCAL _loadds GetSaveFileNamePreviewA(LPOPENFILENAMEA lpofn) { return GetFileNamePreview((LPOPENFILENAME)lpofn, TRUE, FALSE); }
#else
BOOL FAR PASCAL _loadds GetOpenFileNamePreview(LPOPENFILENAME lpofn) { return GetFileNamePreview(lpofn, FALSE, FALSE); }
BOOL FAR PASCAL _loadds GetSaveFileNamePreview(LPOPENFILENAME lpofn) { return GetFileNamePreview(lpofn, TRUE, FALSE); } #endif
|