|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
faxview.c
Abstract:
This file implements a simple TIFF image viewer.
Environment:
WIN32 User Mode
Author:
Wesley Witt (wesw) 17-Feb-1996
--*/
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <shellapi.h>
#include <stdio.h>
#include <stdlib.h>
#include "resource.h"
#include "tifflib.h"
#include "faxutil.h"
#define WM_OPEN_FILE (WM_USER + 501)
#define WM_VIEW_REFRESH (WM_USER + 503)
#define WM_VIEW_CLOSE (WM_USER + 504)
#define TOP 0
#define LEFT 1
#define BOTTOM 2
#define RIGHT 3
#define SEPHEIGHT 7
#define FILLORDER_LSB2MSB 2
typedef struct _TOOLBAR_STATE { ULONG Id; BOOL State; LPSTR Msg; } TOOLBAR_STATE, *PTOOLBAR_STATE;
//
// globals
//
LPBYTE bmiBuf[sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*2)]; PBITMAPINFO bmi = (PBITMAPINFO) bmiBuf; TIFF_INFO TiffInfo; HWND hwndMain; HWND hwndView; HWND hwndEdit; HWND hwndCoolbar; HWND hwndTooltip; HMENU hMenu; HMENU hMenuZoom; HANDLE hTiff; LPBYTE TiffData; DWORD TiffDataSize; DWORD TiffDataLinesAlloc; DWORD CxScreen; DWORD CyScreen; DWORD CxClient; DWORD CyClient; DWORD ScrollWidth; DWORD ScrollHeight; DWORD VScrollMax; DWORD HScrollMax; DWORD VScrollPage; DWORD VScrollLine; DWORD HScrollLine; INT VscrollPos; INT HscrollPos; INT ScrollPosTrack = -1; DWORD Width; DWORD Height; DWORD OrigWidth; DWORD OrigHeight; WCHAR TiffFileName[MAX_PATH*2]; WCHAR PrinterName[MAX_PATH*2]; WCHAR LastDir[MAX_PATH*2]; DWORD CurrPage; HWND hwndToolbar; HWND hwndStatusbar; DWORD ToolbarHeight; DWORD StatusbarHeight; HMENU hmenuFrame; BOOL TiffFileOpened; DWORD CurrZoom; HCURSOR Hourglass; WNDPROC OrigEditProc; BOOL FileIsOpen; HIMAGELIST himlCoolbar; HBITMAP hBitmapBackground; HINSTANCE hInstance;
TBBUTTON TbButton[] = { { -1, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 }, { 0, IDM_FILEOPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 0 }, { 1, IDM_PRINT, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON, {0,0}, 0, 1 }, { 2, IDM_ZOOM, TBSTATE_INDETERMINATE, TBSTYLE_DROPDOWN, {0,0}, 0, 2 }, { -1, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 }, { -1, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 }, { 3, IDM_HELP, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 3 } };
TOOLBAR_STATE ToolbarState[] = { { IDM_FILEOPEN, TRUE, "" }, { IDM_PRINT, TRUE, "" }, { IDM_PAGE_UP, TRUE, "" }, { IDM_PAGE_DOWN, TRUE, "" } };
#define MAX_TOOLBAR_STATES (sizeof(ToolbarState)/sizeof(TOOLBAR_STATE))
double Zooms[] = { 1.00, .90, .80, .70, .60, .50, .40, .30, .20, .10 };
#define MAX_ZOOMS (sizeof(Zooms)/sizeof(double))
//
// prototypes
//
VOID PopUpMsg( LPWSTR format, ... );
LRESULT WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT ChildWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
BOOL ReadTiffData( HANDLE hTiff, LPBYTE *TiffData, DWORD Width, LPDWORD TiffDataLinesAlloc, DWORD PageNumber );
HDC GetPrinterDC( void );
BOOL TiffMailDefault( LPWSTR TiffFileName, LPWSTR ProfileName, LPWSTR Password, PULONG ResultCode );
VOID InitializeStatusBar( HWND hwnd );
BOOL BrowseForFileName( HWND hwnd, LPWSTR FileName, LPWSTR Extension, LPWSTR FileDesc, LPWSTR Dir );
BOOL PrintSetup( HWND hwnd );
HANDLE PrintTiffFile( HWND hwnd, LPWSTR FileName, LPWSTR PrinterName );
BOOL IsFaxViewerDefaultViewer( VOID );
BOOL MakeFaxViewerDefaultViewer( VOID );
BOOL IsItOkToAskForDefault( VOID );
BOOL SetAskForViewerValue( DWORD Ask );
BOOL SaveWindowPlacement( HWND hwnd );
BOOL QueryWindowPlacement( HWND hwnd );
BOOL OpenTiffFile( LPWSTR FileName, HWND hwnd ) { HANDLE _hTiff; TIFF_INFO _TiffInfo; LPBYTE _TiffData; DWORD _TiffDataSize;
_hTiff = TiffOpen( FileName, &_TiffInfo, TRUE ); if (!_hTiff) { PopUpMsg( L"Could not open TIFF file [%s]", FileName ); return FALSE; }
if ( (_TiffInfo.ImageWidth != 1728) || (_TiffInfo.CompressionType != 4 ) ) {
PopUpMsg( L"Not valid MS TIFF file\n" ); TiffClose( _hTiff ); return FALSE;
}
_TiffDataSize = _TiffInfo.ImageHeight * (_TiffInfo.ImageWidth / 8);
_TiffData = (LPBYTE) VirtualAlloc( NULL, _TiffDataSize, MEM_COMMIT, PAGE_READWRITE ); if (!_TiffData) { TiffClose( _hTiff ); PopUpMsg( L"could allocate memory for TIFF data\n" ); return FALSE; }
hTiff = _hTiff; TiffInfo = _TiffInfo; TiffData = _TiffData; TiffDataSize = _TiffDataSize;
TiffDataLinesAlloc = TiffInfo.ImageHeight;
CurrPage = 1; ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, CurrPage );
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi->bmiHeader.biWidth = TiffInfo.ImageWidth; bmi->bmiHeader.biHeight = - (INT) TiffInfo.ImageHeight; bmi->bmiHeader.biPlanes = 1; bmi->bmiHeader.biBitCount = 1; bmi->bmiHeader.biCompression = BI_RGB; bmi->bmiHeader.biSizeImage = 0; bmi->bmiHeader.biXPelsPerMeter = 7874; bmi->bmiHeader.biYPelsPerMeter = 7874; bmi->bmiHeader.biClrUsed = 0; bmi->bmiHeader.biClrImportant = 0;
if (TiffInfo.PhotometricInterpretation) { bmi->bmiColors[0].rgbBlue = 0; bmi->bmiColors[0].rgbGreen = 0; bmi->bmiColors[0].rgbRed = 0; bmi->bmiColors[0].rgbReserved = 0; bmi->bmiColors[1].rgbBlue = 0xff; bmi->bmiColors[1].rgbGreen = 0xff; bmi->bmiColors[1].rgbRed = 0xff; bmi->bmiColors[1].rgbReserved = 0; } else { bmi->bmiColors[0].rgbBlue = 0xff; bmi->bmiColors[0].rgbGreen = 0xff; bmi->bmiColors[0].rgbRed = 0xff; bmi->bmiColors[0].rgbReserved = 0; bmi->bmiColors[1].rgbBlue = 0; bmi->bmiColors[1].rgbGreen = 0; bmi->bmiColors[1].rgbRed = 0; bmi->bmiColors[1].rgbReserved = 0; }
OrigWidth = Width = TiffInfo.ImageWidth; OrigHeight = Height = TiffInfo.ImageHeight;
TiffFileOpened = TRUE;
return TRUE; }
VOID FitRectToScreen( PRECT prc ) { INT cxScreen; INT cyScreen; INT delta;
cxScreen = GetSystemMetrics(SM_CXSCREEN); cyScreen = GetSystemMetrics(SM_CYSCREEN);
if (prc->right > cxScreen) { delta = prc->right - prc->left; prc->right = cxScreen; prc->left = prc->right - delta; }
if (prc->left < 0) { delta = prc->right - prc->left; prc->left = 0; prc->right = prc->left + delta; }
if (prc->bottom > cyScreen) { delta = prc->bottom - prc->top; prc->bottom = cyScreen; prc->top = prc->bottom - delta; }
if (prc->top < 0) { delta = prc->bottom - prc->top; prc->top = 0; prc->bottom = prc->top + delta; } }
VOID CenterWindow( HWND hwnd, HWND hwndToCenterOver ) { RECT rc; RECT rcOwner; RECT rcCenter; HWND hwndOwner;
GetWindowRect( hwnd, &rc );
if (hwndToCenterOver) { hwndOwner = hwndToCenterOver; GetClientRect( hwndOwner, &rcOwner ); } else { hwndOwner = GetWindow( hwnd, GW_OWNER ); if (!hwndOwner) { hwndOwner = GetDesktopWindow(); } GetWindowRect( hwndOwner, &rcOwner ); }
//
// Calculate the starting x,y for the new
// window so that it would be centered.
//
rcCenter.left = rcOwner.left + (((rcOwner.right - rcOwner.left) - (rc.right - rc.left)) / 2);
rcCenter.top = rcOwner.top + (((rcOwner.bottom - rcOwner.top) - (rc.bottom - rc.top)) / 2);
rcCenter.right = rcCenter.left + (rc.right - rc.left); rcCenter.bottom = rcCenter.top + (rc.bottom - rc.top);
FitRectToScreen( &rcCenter );
SetWindowPos(hwnd, NULL, rcCenter.left, rcCenter.top, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); }
LRESULT AskViewerDlgProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_INITDIALOG: CenterWindow( hwnd, GetDesktopWindow() ); break;
case WM_COMMAND: switch( wParam ) { case IDOK: SetAskForViewerValue( !IsDlgButtonChecked( hwnd, IDC_DEFAULT_VIEWER ) == BST_CHECKED ); EndDialog( hwnd, IDOK ); break;
case IDCANCEL: SetAskForViewerValue( !IsDlgButtonChecked( hwnd, IDC_DEFAULT_VIEWER ) == BST_CHECKED ); EndDialog( hwnd, IDCANCEL ); break; } break; }
return FALSE; }
void MoveCoolbar( DWORD HowAlign ) { RECT rc; RECT rcCoolbar; int x; int y; int cx; int cy;
GetClientRect( hwndMain, &rc ); GetWindowRect( hwndCoolbar, &rcCoolbar );
switch( HowAlign ) { default: case TOP: x = 0; y = 0; cx = rc.right - rc.left; cy = rc.bottom - rc.top; break;
case LEFT: x = 0; y = 0; cx = rcCoolbar.right - rcCoolbar.left; cy = rc.bottom - rc.top; break;
case BOTTOM: x = 0; y = rc.bottom - (rcCoolbar.bottom - rcCoolbar.top); cx = rc.right - rc.left; cy = rcCoolbar.bottom - rcCoolbar.top; break;
case RIGHT: x = rc.right - (rcCoolbar.right - rcCoolbar.left); y = 0; cx = rcCoolbar.right - rcCoolbar.left; cy = rc.bottom - rc.top; break; }
MoveWindow( hwndCoolbar, x, y, cx, cy, TRUE ); }
VOID LoadBackgroundBitmap( VOID ) { COLORREF clrFace; HBITMAP hbmSave; UINT n; UINT i; RGBQUAD rgbTable[256]; RGBQUAD rgbFace; HDC hdc;
if (hBitmapBackground) { DeleteObject( hBitmapBackground ); }
hBitmapBackground = (HBITMAP) LoadImage( hInstance, MAKEINTRESOURCE(IDB_COOLBAR), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION );
hdc = CreateCompatibleDC(NULL); clrFace = GetSysColor(COLOR_BTNFACE);
if (clrFace != RGB(192,192,192)) {
hbmSave = (HBITMAP) SelectObject( hdc, hBitmapBackground ); n = GetDIBColorTable(hdc, 0, 256, rgbTable);
rgbFace.rgbRed = GetRValue(clrFace); rgbFace.rgbGreen = GetGValue(clrFace); rgbFace.rgbBlue = GetBValue(clrFace);
for (i = 0; i < n; i++) { rgbTable[i].rgbRed = (rgbTable[i].rgbRed * rgbFace.rgbRed ) / 192; rgbTable[i].rgbGreen = (rgbTable[i].rgbGreen * rgbFace.rgbGreen) / 192; rgbTable[i].rgbBlue = (rgbTable[i].rgbBlue * rgbFace.rgbBlue ) / 192; }
SetDIBColorTable(hdc, 0, n, rgbTable); SelectObject(hdc, hbmSave); }
DeleteDC( hdc ); }
VOID SetBackground( VOID ) { REBARBANDINFO rbbi; DWORD fMask;
LoadBackgroundBitmap();
if (hBitmapBackground) { fMask = RBBIM_BACKGROUND; rbbi.hbmBack = hBitmapBackground; } else { fMask = RBBIM_BACKGROUND | RBBIM_COLORS; rbbi.hbmBack = NULL; rbbi.clrFore = GetSysColor(COLOR_BTNTEXT); rbbi.clrBack = GetSysColor(COLOR_BTNFACE); }
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_ID | RBBIM_CHILD; if (SendMessage( hwndCoolbar, RB_GETBANDINFO, 0, (LPARAM) &rbbi )) { rbbi.fMask = fMask; SendMessage( hwndCoolbar, RB_SETBANDINFO, 0, (LPARAM) &rbbi ); InvalidateRect( rbbi.hwndChild, NULL, TRUE ); } }
int WINAPI wWinMain( HINSTANCE hInst, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd )
/*++
Routine Description:
Main entry point for the TIFF image viewer.
Arguments:
hInstance - Instance handle hPrevInstance - Not used lpCmdLine - Command line arguments nShowCmd - How to show the window
Return Value:
Return code, zero for success.
--*/
{ LPWSTR *argv; DWORD argc; WNDCLASS wc; MSG msg; RECT rect; DWORD i; HANDLE hThread; LOGBRUSH lb; RECT rc; TBADDBITMAP tbab; INITCOMMONCONTROLSEX iccex; REBARBANDINFO rbbi; LRESULT lButtonSize;
hInstance = hInst;
//
// general init code
//
HeapInitialize(NULL,NULL,NULL,0);
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); iccex.dwICC = ICC_COOL_CLASSES; InitCommonControlsEx( &iccex );
FaxTiffInitialize();
//
// process the command line
//
argv = CommandLineToArgvW( GetCommandLine(), &argc );
for (i=1; i<argc; i++) { if (argv[i][0] == L'-' || argv[i][0] == L'/') { switch (towlower(argv[i][1])) { case L'p': if (towlower(argv[i][2]) == L't') { hThread = PrintTiffFile( NULL, argv[i+1], argv[i+2] ); } else { hThread = PrintTiffFile( NULL, argv[i+1], NULL ); } if (hThread) { WaitForSingleObject( hThread, INFINITE ); } return 0;
default: break; } } else { //
// must be a file name for viewing
//
wcscpy( TiffFileName, argv[i] ); } }
if ((!IsFaxViewerDefaultViewer()) && IsItOkToAskForDefault()) { int Answer = DialogBox( hInstance, MAKEINTRESOURCE(IDD_VIEWER), NULL, AskViewerDlgProc ); if (Answer == IDOK) { MakeFaxViewerDefaultViewer(); } }
CxScreen = GetSystemMetrics( SM_CXSCREEN ); CyScreen = GetSystemMetrics( SM_CYSCREEN );
ScrollWidth = GetSystemMetrics( SM_CYVSCROLL ); ScrollHeight = GetSystemMetrics( SM_CYHSCROLL );
CurrPage = 1;
wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wc.lpszMenuName = MAKEINTRESOURCE( FAXVIEW ); wc.lpszClassName = L"FaxView";
if (!RegisterClass(&wc)) { return FALSE; }
lb.lbStyle = BS_SOLID; lb.lbColor = RGB( 221,232,23 ); lb.lbHatch = 0;
wc.lpfnWndProc = (WNDPROC)ChildWndProc; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_CROSS); wc.lpszMenuName = NULL; wc.lpszClassName = L"FaxViewChild";
if (!RegisterClass(&wc)) { return FALSE; }
hwndMain = CreateWindow( L"FaxView", // window class name
L"FaxView", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL // creation parameters
);
if (!hwndMain) { return 0; }
hMenu = GetMenu( hwndMain ); hMenuZoom = GetSubMenu( GetSubMenu( hMenu, 1 ), 3 );
Hourglass = LoadCursor( NULL, IDC_WAIT ); if (!Hourglass) { DebugPrint(( L"LoadCursor() failed for IDC_WAIT, ec=%d", GetLastError() )); }
//
// create the coolbar
//
hwndCoolbar = CreateWindowEx( WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_TOOLTIPS | RBS_BANDBORDERS | CCS_NODIVIDER | CCS_NOPARENTALIGN, 0, 0, 200, 100, hwndMain, (HMENU) IDM_COOLBAR, hInstance, NULL ); if (!hwndCoolbar) { return 0; }
//
// create and populate the toolbar
//
hwndToolbar = CreateWindowEx( WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_FLAT | CCS_ADJUSTABLE | CCS_NODIVIDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NOPARENTALIGN, 0, 0, 0, 0, hwndCoolbar, (HMENU) IDM_TOOLBAR, hInstance, NULL );
SendMessage( hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0 );
SendMessage( hwndToolbar, TB_SETMAXTEXTROWS, 2, 0 ); SendMessage( hwndToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24,24) );
tbab.hInst = hInstance; tbab.nID = IDB_OPEN_BIG; SendMessage( hwndToolbar, TB_ADDBITMAP, 1, (LPARAM) &tbab );
tbab.nID = IDB_PRINT_BIG; SendMessage( hwndToolbar, TB_ADDBITMAP, 1, (LPARAM) &tbab );
tbab.nID = IDB_ZOOM_BIG; SendMessage( hwndToolbar, TB_ADDBITMAP, 1, (LPARAM) &tbab );
tbab.nID = IDB_HELP_BIG; SendMessage( hwndToolbar, TB_ADDBITMAP, 1, (LPARAM) &tbab );
SendMessage( hwndToolbar, TB_ADDSTRING, 0, (LPARAM) L"Open\0Print\0Zoom\0Help\0\0" ); SendMessage( hwndToolbar, TB_ADDBUTTONS, sizeof(TbButton)/sizeof(TBBUTTON), (LPARAM)&TbButton );
SendMessage( hwndToolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(50,200) );
ShowWindow( hwndToolbar, SW_SHOW );
//
// add the toolbar to the coolbar
//
lButtonSize = SendMessage( hwndToolbar, TB_GETBUTTONSIZE, 0, 0 );
ZeroMemory( &rbbi, sizeof(rbbi) );
rbbi.cbSize = sizeof(REBARBANDINFO); rbbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_ID | RBBIM_STYLE | RBBIM_COLORS ; rbbi.cxMinChild = LOWORD(lButtonSize); rbbi.cyMinChild = HIWORD(lButtonSize); rbbi.clrFore = GetSysColor(COLOR_BTNTEXT); rbbi.clrBack = GetSysColor(COLOR_BTNFACE); rbbi.fStyle = RBBS_CHILDEDGE | RBBS_FIXEDBMP; rbbi.wID = IDM_TOOLBAR; rbbi.hwndChild = hwndToolbar; rbbi.lpText = NULL; rbbi.hbmBack = NULL; rbbi.iImage = 0;
SendMessage( hwndCoolbar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbbi );
SetBackground();
MoveCoolbar( TOP );
GetWindowRect( hwndCoolbar, &rc ); ToolbarHeight = rc.bottom - rc.top - 1;
hwndStatusbar = CreateStatusWindow( WS_CHILD | WS_VISIBLE | WS_BORDER, L"Fax Viewer", hwndMain, IDM_STATUSBAR ); GetWindowRect( hwndStatusbar, &rect ); StatusbarHeight = rect.bottom - rect.top; InitializeStatusBar( hwndMain );
if (TiffFileName[0]) { PostMessage( hwndMain, WM_OPEN_FILE, 0, (LPARAM) TiffFileName ); }
GetClientRect( hwndMain, &rc );
hwndView = CreateWindow( L"FaxViewChild", // window class name
NULL, // window caption
WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, // window style
rc.left, // initial x position
rc.top + ToolbarHeight + SEPHEIGHT, // initial y position
rc.right - rc.left, // initial x size
rc.bottom - rc.top - ToolbarHeight - SEPHEIGHT - StatusbarHeight, // initial y size
hwndMain, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL // creation parameters
);
if (!hwndView) { return 0; }
hwndTooltip = CreateWindowEx( WS_EX_TOOLWINDOW, TOOLTIPS_CLASS, NULL, WS_CHILD, 0, 0, 0, 0, hwndView, (HMENU) IDM_TOOLTIP, hInstance, NULL );
if (!hwndTooltip) { return 0; }
ShowWindow( hwndMain, SW_SHOWNORMAL ); ShowWindow( hwndView, SW_SHOWNORMAL );
UpdateWindow( hwndMain ); UpdateWindow( hwndView ); InvalidateRect( hwndView, NULL, TRUE );
while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; }
return 0; }
BOOL ReadTiffData( HANDLE hTiff, LPBYTE *TiffData, DWORD Width, LPDWORD TiffDataLinesAlloc, DWORD PageNumber ) { DWORD Lines = 0;
TiffSeekToPage( hTiff, PageNumber, FILLORDER_LSB2MSB );
TiffUncompressMmrPage( hTiff, (LPDWORD) *TiffData, &Lines );
if (Lines > *TiffDataLinesAlloc) {
*TiffDataLinesAlloc = Lines;
VirtualFree( *TiffData, 0, MEM_RELEASE );
*TiffData = (LPBYTE) VirtualAlloc( NULL, Lines * (Width / 8), MEM_COMMIT, PAGE_READWRITE ); if (!*TiffData) { return FALSE; } }
if (!TiffUncompressMmrPage( hTiff, (LPDWORD) *TiffData, &Lines )) { return FALSE; }
EnableMenuItem( hMenu, IDM_PAGE_UP, PageNumber == 1 ? MF_GRAYED : MF_ENABLED );
return TRUE; }
VOID PopUpMsg( LPWSTR format, ... )
/*++
Routine Description:
Pops up a message box to indicate an error.
Arguments:
format - Format string ... - Other arguments
Return Value:
None.
--*/
{ WCHAR buf[1024]; va_list arg_ptr;
va_start( arg_ptr, format ); _vsnwprintf( buf, sizeof(buf), format, arg_ptr ); va_end( arg_ptr );
MessageBox( NULL, buf, L"FaxView", MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION ); }
VOID ChangeTitle( HWND hwnd, LPWSTR FileName )
/*++
Routine Description:
Changes the title text of the window.
Arguments:
hwnd - Window handle
Return Value:
None.
--*/
{ LPWSTR p; WCHAR WindowTitle[128];
p = wcsrchr( FileName, L'\\' ); if (p) { FileName = p + 1; }
if (TiffFileName[0]) { swprintf( WindowTitle, L"FaxView - %s Page %d of %d", FileName, CurrPage, TiffInfo.PageCount ); } else { swprintf( WindowTitle, L"FaxView" ); } SetWindowText( hwnd, WindowTitle ); }
VOID UpdateStatusBar( LPWSTR lpszStatusString, WORD partNumber, WORD displayFlags ) { SendMessage( hwndStatusbar, SB_SETTEXT, partNumber | displayFlags, (LPARAM)lpszStatusString ); }
VOID InitializeStatusBar( HWND hwnd ) { UpdateStatusBar( L"Fax Viewer", 0, 0 ); }
LRESULT WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
/*++
Routine Description:
Window procedure for the TIFF image viewer main window.
Arguments:
hwnd - Window handle message - message identifier wParam - Parameter lParam - Parameter
Return Value:
Return result, zero for success.
--*/
{ HDC hdc; RECT rc; HCURSOR OldCursor; BOOL ReOpen; PAINTSTRUCT ps; LPWSTR p; WCHAR FileName[MAX_PATH*2];
switch (message) { case WM_CREATE: hmenuFrame = GetMenu( hwnd ); QueryWindowPlacement( hwnd ); return 0;
case WM_PAINT: GetClientRect( hwnd, &rc ); rc.top += ToolbarHeight; rc.bottom = rc.top + SEPHEIGHT; hdc = BeginPaint( hwnd, &ps ); DrawEdge( hdc, &rc, EDGE_RAISED, BF_TOP | BF_BOTTOM | BF_MIDDLE ); EndPaint( hwnd, &ps ); return 0;
case WM_OPEN_FILE: ReOpen = FALSE; wcscpy( FileName, (LPWSTR) lParam ); goto open_file; return 0;
case WM_NOTIFY: if (((LPNMHDR)lParam)->code == TBN_DROPDOWN) { SendMessage( hwndToolbar, TB_GETRECT, IDM_ZOOM, (LPARAM)&rc ); rc.top = rc.bottom; MapWindowPoints( hwndToolbar, HWND_DESKTOP, (POINT *)&rc, 2 ); TrackPopupMenu( hMenuZoom, TPM_LEFTALIGN | TPM_LEFTBUTTON, rc.left, rc.top, 0, hwnd, NULL ); } return 0;
case WM_COMMAND:
if (HIWORD(wParam) == 0) { switch( wParam ) { case IDM_FILEOPEN:
ReOpen = TiffFileOpened;
//
// ask the user to choose a file name
//
if (!BrowseForFileName( hwnd, FileName, L"tif", L"Fax Image Files", LastDir )) { return 0; } open_file:
if (!OpenTiffFile( FileName, hwnd )) { return 0; }
//
// update the last directory name
//
p = wcsrchr( FileName, L'\\' ); if (p) { wcscpy( LastDir, FileName ); p = wcsrchr( LastDir, L'\\' ); if (p) { *p = 0; } }
wcscpy( TiffFileName, FileName );
OldCursor = SetCursor( Hourglass );
if (ReOpen) { TiffFileOpened = FALSE; TiffClose( hTiff ); VirtualFree( TiffData, 0, MEM_RELEASE ); TiffData = NULL; hTiff = NULL; Width = 0; Height = 0; OrigWidth = 0; OrigHeight = 0; TiffDataSize = 0; SendMessage( hwndView, WM_VIEW_CLOSE, 0, 0 ); }
ChangeTitle( hwnd, TiffFileName ); SendMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
SetCursor( OldCursor );
EnableMenuItem( hMenu, IDM_CLOSE, MF_ENABLED ); EnableMenuItem( hMenu, IDM_PRINT, MF_ENABLED ); EnableMenuItem( hMenu, IDM_PRINT_SETUP, MF_ENABLED ); EnableMenuItem( hMenu, IDM_ZOOM, MF_ENABLED ); EnableMenuItem( hMenu, IDM_PAGE_UP, MF_GRAYED );
if (TiffInfo.PageCount > 1) { EnableMenuItem( hMenu, IDM_PAGE_DOWN, MF_ENABLED ); }
SendMessage( hwndToolbar, TB_SETSTATE, IDM_PRINT, (LPARAM) MAKELONG(TBSTATE_ENABLED, 0) ); SendMessage( hwndToolbar, TB_SETSTATE, IDM_ZOOM, (LPARAM) MAKELONG(TBSTATE_ENABLED, 0) ); return 0;
case IDM_ZOOM_100: case IDM_ZOOM_90: case IDM_ZOOM_80: case IDM_ZOOM_70: case IDM_ZOOM_60: case IDM_ZOOM_50: case IDM_ZOOM_40: case IDM_ZOOM_30: case IDM_ZOOM_20: case IDM_ZOOM_10: CheckMenuItem( hMenuZoom, CurrZoom+IDM_ZOOM_100, MF_UNCHECKED ); CheckMenuItem( hMenuZoom, wParam, MF_CHECKED ); CurrZoom = wParam - IDM_ZOOM_100; SendMessage( hwndView, WM_VIEW_REFRESH, 0, 0 ); return 0;
case IDM_PAGE_UP: if (CurrPage == 1) { MessageBeep( MB_ICONEXCLAMATION ); return 0; } ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, --CurrPage ); ChangeTitle( hwnd, TiffFileName ); SendMessage( hwndView, WM_VIEW_REFRESH, 0, 0 ); return 0;
case IDM_PAGE_DOWN: if (CurrPage == TiffInfo.PageCount) { MessageBeep( MB_ICONEXCLAMATION ); return 0; } ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, ++CurrPage ); ChangeTitle( hwnd, TiffFileName ); SendMessage( hwndView, WM_VIEW_REFRESH, 0, 0 ); return 0;
case IDM_PRINT_SETUP: PrintSetup( hwnd ); return 0;
case IDM_PRINT: PrintTiffFile( hwnd, TiffFileName, NULL ); return 0;
case IDM_CLOSE:
TiffFileOpened = FALSE; TiffClose( hTiff ); VirtualFree( TiffData, 0, MEM_RELEASE ); TiffData = NULL; hTiff = NULL; Width = 0; Height = 0; OrigWidth = 0; OrigHeight = 0; TiffDataSize = 0; TiffFileName[0] = 0; ChangeTitle( hwnd, TiffFileName );
SendMessage( hwndView, WM_VIEW_CLOSE, 0, 0 );
EnableMenuItem( hMenu, IDM_CLOSE, MF_GRAYED ); EnableMenuItem( hMenu, IDM_PRINT, MF_GRAYED ); EnableMenuItem( hMenu, IDM_PRINT_SETUP, MF_GRAYED ); EnableMenuItem( hMenu, IDM_PAGE_UP, MF_GRAYED ); EnableMenuItem( hMenu, IDM_PAGE_DOWN, MF_GRAYED ); EnableMenuItem( hMenu, IDM_ZOOM, MF_GRAYED );
SendMessage( hwndToolbar, TB_SETSTATE, IDM_PRINT, (LPARAM) MAKELONG(TBSTATE_INDETERMINATE, 0) ); SendMessage( hwndToolbar, TB_SETSTATE, IDM_ZOOM, (LPARAM) MAKELONG(TBSTATE_INDETERMINATE, 0) );
return 0;
case IDM_EXIT: PostQuitMessage( 0 ); return 0;
case IDM_HELP: WinHelp(hwnd, TEXT( "faxview.HLP" ), HELP_FINDER, 0L); return 0;
case IDM_ABOUT: ShellAbout( hwnd, L"Fax Viewer", NULL, NULL ); break; } } return 0;
case WM_SIZE: MoveCoolbar( TOP ); SendMessage( hwndToolbar, message, wParam, lParam ); SendMessage( hwndStatusbar, message, wParam, lParam );
InitializeStatusBar( hwnd );
CyClient = HIWORD(lParam) - ToolbarHeight - SEPHEIGHT - StatusbarHeight; CxClient = LOWORD(lParam);
//
// resize the view window
//
GetClientRect( hwnd, &rc ); MoveWindow( hwndView, rc.left, rc.top+ToolbarHeight+SEPHEIGHT, CxClient, CyClient, TRUE ); return 0;
case WM_KEYDOWN: switch( wParam ) { case VK_NEXT: if (GetKeyState( VK_CONTROL ) & 0x8000) { SendMessage( hwnd, WM_COMMAND, IDM_PAGE_DOWN, 0 ); } else { SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_PAGEDOWN,0), 0 ); } break;
case VK_PRIOR: if (GetKeyState( VK_CONTROL ) & 0x8000) { SendMessage( hwnd, WM_COMMAND, IDM_PAGE_UP, 0 ); } else { SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_PAGEUP,0), 0 ); } break;
case VK_END: SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_BOTTOM,0), 0 ); break;
case VK_HOME: SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_TOP,0), 0 ); break;
case VK_LEFT: SendMessage( hwndView, WM_HSCROLL, MAKELONG(SB_LINELEFT,0), 0 ); break;
case VK_RIGHT: SendMessage( hwndView, WM_HSCROLL, MAKELONG(SB_LINERIGHT,0), 0 ); break;
case VK_UP: SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_LINEUP,0), 0 ); break;
case VK_DOWN: SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_LINEDOWN,0), 0 ); break;
case VK_F4: SendMessage( hwnd, WM_COMMAND, IDM_FILEOPEN, 0 ); break;
case VK_F1: SendMessage( hwnd, WM_COMMAND, IDM_HELP, 0 ); break; } return 0;
case WM_SYSCOLORCHANGE: SendMessage( hwndCoolbar, message, wParam, lParam ); SetBackground(); return 0;
case WM_DESTROY: SaveWindowPlacement( hwnd ); PostQuitMessage( 0 ); return 0; }
return DefWindowProc( hwnd, message, wParam, lParam ); }
VOID UpdateScrollInfo( HWND hwnd ) { SCROLLINFO si;
//
// set the vertical scroll amounts for pages & lines
//
if (TiffInfo.PageCount) { VScrollMax = TiffInfo.PageCount * Height; VScrollPage = Height; VScrollLine = VScrollPage / 10; HScrollLine = TiffInfo.ImageWidth / 10; } else { VScrollMax = 0; VScrollPage = 0; VScrollLine = 0; }
si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_RANGE;
GetScrollInfo( hwnd, SB_VERT, &si );
si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_RANGE; si.nMin = 0; si.nMax = VScrollMax; si.nPage = CyClient;
SetScrollInfo( hwnd, SB_VERT, &si, TRUE );
si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_RANGE;
GetScrollInfo( hwnd, SB_HORZ, &si );
HScrollMax = Width - CxClient;
si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_RANGE; si.nMin = 0; si.nMax = HScrollMax; si.nPage = CxClient;
SetScrollInfo( hwnd, SB_HORZ, &si, TRUE ); }
DWORD ScrollPosToPage( DWORD ScrollPos ) { DWORD Page = 0;
Page = ScrollPos / VScrollPage; Page = Page + (((ScrollPos % VScrollPage) > 0) ? 1 : 0);
return Page == 0 ? 1 : Page; }
VOID ScrollViewVertically( HWND hwnd, INT ScrollCode, INT Position ) { INT OldScrollPos; RECT rcClip; INT Delta; SCROLLINFO si; DWORD NewPage; DWORD Remaining;
OldScrollPos = VscrollPos;
if (ScrollCode == SB_LINEUP || ScrollCode == SB_LINEDOWN) {
if (ScrollCode == SB_LINEUP) { VscrollPos -= VScrollLine; } else { VscrollPos += VScrollLine; } line_scroll: VscrollPos = max( 0, min( VscrollPos, (int) VScrollMax ) ); SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); Delta = VscrollPos - OldScrollPos;
if (Delta == 0) {
MessageBeep( MB_ICONASTERISK ); return;
} else if (Delta > 0) {
if (VscrollPos < (INT)VScrollPage) { Remaining = VScrollPage - VscrollPos; } else if (VscrollPos % VScrollPage == 0) { Remaining = 0; } else { Remaining = TiffInfo.ImageHeight - (VscrollPos % VScrollPage); } if (Remaining < CyClient) { VscrollPos -= (CyClient - Remaining); Delta -= (CyClient - Remaining); if (Delta == 0) { //
// advance to the next page
//
if (CurrPage == TiffInfo.PageCount) { MessageBeep( MB_ICONASTERISK ); VscrollPos = OldScrollPos; return; } ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, ++CurrPage ); ChangeTitle( hwndMain, TiffFileName ); VscrollPos = VScrollPage*(CurrPage-1); SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 ); return; } SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); }
GetClientRect( hwnd, &rcClip ); ScrollWindow( hwnd, 0, -Delta, NULL, &rcClip );
} else {
if (OldScrollPos % VScrollPage == 0) { //
// advance to the previous page
//
if (CurrPage == 1) { MessageBeep( MB_ICONASTERISK ); return; } ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, --CurrPage ); ChangeTitle( hwndMain, TiffFileName ); VscrollPos = VScrollPage * (CurrPage - 1) + TiffInfo.ImageHeight - CyClient; SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 ); return; }
if (ScrollPosToPage( VscrollPos ) != CurrPage) { //
// the file was positioned just below the top
// of the previous page, so lets align to the beginning
// of the current page
//
Remaining = -((INT)OldScrollPos - ((INT)CurrPage - 1) * (INT)TiffInfo.ImageHeight); VscrollPos -= Delta - Remaining; Delta = Remaining;
}
GetClientRect( hwnd, &rcClip ); ScrollWindow( hwnd, 0, -Delta, NULL, &rcClip ); } return; }
if (ScrollCode == SB_THUMBTRACK) { if (ScrollPosTrack == -1) { ScrollPosTrack = VscrollPos; } VscrollPos = max( 0, min( Position, (int) VScrollMax ) ); SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); return; }
if (ScrollCode == SB_ENDSCROLL && ScrollPosTrack != -1) { si.cbSize = sizeof(SCROLLINFO); si.fMask = SIF_POS; GetScrollInfo( hwnd, SB_VERT, &si ); VscrollPos = si.nPos; Delta = VscrollPos - ScrollPosTrack; ScrollPosTrack = -1; NewPage = ScrollPosToPage( VscrollPos ); if (NewPage != CurrPage) { //
// the user changed pages
//
CurrPage = NewPage; ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, CurrPage ); ChangeTitle( hwndMain, TiffFileName ); VscrollPos = VScrollPage*(CurrPage-1); SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 ); return; } else { SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); if (Delta != 0) { GetClientRect( hwnd, &rcClip ); ScrollWindow( hwnd, 0, -Delta, NULL, &rcClip ); } return; } return; }
if (ScrollCode == SB_PAGEDOWN) { VscrollPos += CyClient; goto line_scroll; return; }
if (ScrollCode == SB_PAGEUP) { VscrollPos -= CyClient; goto line_scroll; return; }
if (ScrollCode == SB_TOP) { CurrPage = 1; ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, CurrPage ); ChangeTitle( hwndMain, TiffFileName ); VscrollPos = 0; SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 ); return; }
if (ScrollCode == SB_BOTTOM) { CurrPage = TiffInfo.PageCount; ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, CurrPage ); ChangeTitle( hwndMain, TiffFileName ); VscrollPos = 0; SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE ); PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 ); return; } }
LRESULT ChildWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { static double ZoomPct = 1.00; static HDC hdcMem = NULL;
RECT rc; PAINTSTRUCT ps; HDC hdc; HCURSOR OldCursor; int OldScrollPos; int Delta; HBITMAP hBmp;
switch (message) {
case WM_CREATE: ZoomPct = Zooms[CurrZoom]; return 0;
case WM_VSCROLL: ScrollViewVertically( hwnd, LOWORD(wParam), HIWORD(wParam) ); UpdateScrollInfo( hwnd ); return 0;
case WM_HSCROLL: OldScrollPos = HscrollPos;
GetClientRect( hwnd, &rc );
switch (LOWORD (wParam)) { case SB_LINEUP: HscrollPos -= HScrollLine; break;
case SB_LINEDOWN: HscrollPos += HScrollLine; break;
case SB_PAGEUP: HscrollPos -= CxClient; break;
case SB_PAGEDOWN: HscrollPos += CxClient; break;
case SB_THUMBPOSITION: HscrollPos = HIWORD(wParam); break;
case SB_THUMBTRACK: HscrollPos = HIWORD(wParam); break; }
HscrollPos = max( 0, min( HscrollPos, (int) HScrollMax ) );
SetScrollPos( hwnd, SB_HORZ, HscrollPos, TRUE );
Delta = HscrollPos - OldScrollPos; if (Delta != 0) { ScrollWindow( hwnd, -Delta, 0, &rc, &rc ); } return 0;
case WM_PAINT: hdc = BeginPaint( hwnd, &ps ); if (TiffFileOpened) { GetClientRect( hwnd, &rc ); BitBlt( hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, hdcMem, HscrollPos + ((int)ps.rcPaint.left - (int)rc.left), (VscrollPos%VScrollPage) + ((int)ps.rcPaint.top - (int)rc.top), SRCCOPY ); } EndPaint( hwnd, &ps ); return 0;
case WM_VIEW_CLOSE: DeleteDC( hdcMem ); hdcMem = NULL; VscrollPos = 0; HscrollPos = 0; UpdateScrollInfo( hwnd ); return 0;
case WM_VIEW_REFRESH: ZoomPct = Zooms[CurrZoom];
HscrollPos = 0; Width = (DWORD)(OrigWidth * ZoomPct); Height = (DWORD)(OrigHeight * ZoomPct);
SetScrollPos( hwnd, SB_HORZ, HscrollPos, TRUE );
OldCursor = SetCursor( Hourglass ); DeleteDC( hdcMem );
hdc = GetDC( hwnd ); hBmp = CreateCompatibleBitmap( hdc, Width, Height ); hdcMem = CreateCompatibleDC( hdc ); SelectObject( hdcMem, hBmp );
StretchDIBits( hdcMem, 0, 0, Width, Height, 0, 0, TiffInfo.ImageWidth, TiffInfo.ImageHeight, TiffData, bmi, DIB_RGB_COLORS, SRCCOPY );
ReleaseDC( hwnd, hdc ); DeleteObject( hBmp );
UpdateScrollInfo( hwnd );
InvalidateRect( hwnd, NULL, TRUE );
SetCursor( OldCursor ); return 0;
case WM_SIZE: UpdateScrollInfo( hwnd ); GetClientRect( hwnd, &rc ); CyClient = rc.bottom - rc.top; CxClient = rc.right - rc.left; return 0; }
return DefWindowProc( hwnd, message, wParam, lParam ); }
|