Source code of Windows XP (NT5)
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.

1821 lines
46 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. faxview.c
  5. Abstract:
  6. This file implements a simple TIFF image viewer.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Wesley Witt (wesw) 17-Feb-1996
  11. --*/
  12. #include <windows.h>
  13. #include <commctrl.h>
  14. #include <commdlg.h>
  15. #include <shellapi.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include "resource.h"
  19. #include "tifflib.h"
  20. #include "faxutil.h"
  21. #define WM_OPEN_FILE (WM_USER + 501)
  22. #define WM_VIEW_REFRESH (WM_USER + 503)
  23. #define WM_VIEW_CLOSE (WM_USER + 504)
  24. #define TOP 0
  25. #define LEFT 1
  26. #define BOTTOM 2
  27. #define RIGHT 3
  28. #define SEPHEIGHT 7
  29. #define FILLORDER_LSB2MSB 2
  30. typedef struct _TOOLBAR_STATE {
  31. ULONG Id;
  32. BOOL State;
  33. LPSTR Msg;
  34. } TOOLBAR_STATE, *PTOOLBAR_STATE;
  35. //
  36. // globals
  37. //
  38. LPBYTE bmiBuf[sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*2)];
  39. PBITMAPINFO bmi = (PBITMAPINFO) bmiBuf;
  40. TIFF_INFO TiffInfo;
  41. HWND hwndMain;
  42. HWND hwndView;
  43. HWND hwndEdit;
  44. HWND hwndCoolbar;
  45. HWND hwndTooltip;
  46. HMENU hMenu;
  47. HMENU hMenuZoom;
  48. HANDLE hTiff;
  49. LPBYTE TiffData;
  50. DWORD TiffDataSize;
  51. DWORD TiffDataLinesAlloc;
  52. DWORD CxScreen;
  53. DWORD CyScreen;
  54. DWORD CxClient;
  55. DWORD CyClient;
  56. DWORD ScrollWidth;
  57. DWORD ScrollHeight;
  58. DWORD VScrollMax;
  59. DWORD HScrollMax;
  60. DWORD VScrollPage;
  61. DWORD VScrollLine;
  62. DWORD HScrollLine;
  63. INT VscrollPos;
  64. INT HscrollPos;
  65. INT ScrollPosTrack = -1;
  66. DWORD Width;
  67. DWORD Height;
  68. DWORD OrigWidth;
  69. DWORD OrigHeight;
  70. WCHAR TiffFileName[MAX_PATH*2];
  71. WCHAR PrinterName[MAX_PATH*2];
  72. WCHAR LastDir[MAX_PATH*2];
  73. DWORD CurrPage;
  74. HWND hwndToolbar;
  75. HWND hwndStatusbar;
  76. DWORD ToolbarHeight;
  77. DWORD StatusbarHeight;
  78. HMENU hmenuFrame;
  79. BOOL TiffFileOpened;
  80. DWORD CurrZoom;
  81. HCURSOR Hourglass;
  82. WNDPROC OrigEditProc;
  83. BOOL FileIsOpen;
  84. HIMAGELIST himlCoolbar;
  85. HBITMAP hBitmapBackground;
  86. HINSTANCE hInstance;
  87. TBBUTTON TbButton[] =
  88. {
  89. { -1, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 },
  90. { 0, IDM_FILEOPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 0 },
  91. { 1, IDM_PRINT, TBSTATE_INDETERMINATE, TBSTYLE_BUTTON, {0,0}, 0, 1 },
  92. { 2, IDM_ZOOM, TBSTATE_INDETERMINATE, TBSTYLE_DROPDOWN, {0,0}, 0, 2 },
  93. { -1, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 },
  94. { -1, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 },
  95. { 3, IDM_HELP, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 3 }
  96. };
  97. TOOLBAR_STATE ToolbarState[] =
  98. {
  99. { IDM_FILEOPEN, TRUE, "" },
  100. { IDM_PRINT, TRUE, "" },
  101. { IDM_PAGE_UP, TRUE, "" },
  102. { IDM_PAGE_DOWN, TRUE, "" }
  103. };
  104. #define MAX_TOOLBAR_STATES (sizeof(ToolbarState)/sizeof(TOOLBAR_STATE))
  105. double Zooms[] =
  106. {
  107. 1.00,
  108. .90,
  109. .80,
  110. .70,
  111. .60,
  112. .50,
  113. .40,
  114. .30,
  115. .20,
  116. .10
  117. };
  118. #define MAX_ZOOMS (sizeof(Zooms)/sizeof(double))
  119. //
  120. // prototypes
  121. //
  122. VOID
  123. PopUpMsg(
  124. LPWSTR format,
  125. ...
  126. );
  127. LRESULT
  128. WndProc(
  129. HWND hwnd,
  130. UINT message,
  131. WPARAM wParam,
  132. LPARAM lParam
  133. );
  134. LRESULT
  135. ChildWndProc(
  136. HWND hwnd,
  137. UINT message,
  138. WPARAM wParam,
  139. LPARAM lParam
  140. );
  141. BOOL
  142. ReadTiffData(
  143. HANDLE hTiff,
  144. LPBYTE *TiffData,
  145. DWORD Width,
  146. LPDWORD TiffDataLinesAlloc,
  147. DWORD PageNumber
  148. );
  149. HDC
  150. GetPrinterDC(
  151. void
  152. );
  153. BOOL
  154. TiffMailDefault(
  155. LPWSTR TiffFileName,
  156. LPWSTR ProfileName,
  157. LPWSTR Password,
  158. PULONG ResultCode
  159. );
  160. VOID
  161. InitializeStatusBar(
  162. HWND hwnd
  163. );
  164. BOOL
  165. BrowseForFileName(
  166. HWND hwnd,
  167. LPWSTR FileName,
  168. LPWSTR Extension,
  169. LPWSTR FileDesc,
  170. LPWSTR Dir
  171. );
  172. BOOL
  173. PrintSetup(
  174. HWND hwnd
  175. );
  176. HANDLE
  177. PrintTiffFile(
  178. HWND hwnd,
  179. LPWSTR FileName,
  180. LPWSTR PrinterName
  181. );
  182. BOOL
  183. IsFaxViewerDefaultViewer(
  184. VOID
  185. );
  186. BOOL
  187. MakeFaxViewerDefaultViewer(
  188. VOID
  189. );
  190. BOOL
  191. IsItOkToAskForDefault(
  192. VOID
  193. );
  194. BOOL
  195. SetAskForViewerValue(
  196. DWORD Ask
  197. );
  198. BOOL
  199. SaveWindowPlacement(
  200. HWND hwnd
  201. );
  202. BOOL
  203. QueryWindowPlacement(
  204. HWND hwnd
  205. );
  206. BOOL
  207. OpenTiffFile(
  208. LPWSTR FileName,
  209. HWND hwnd
  210. )
  211. {
  212. HANDLE _hTiff;
  213. TIFF_INFO _TiffInfo;
  214. LPBYTE _TiffData;
  215. DWORD _TiffDataSize;
  216. _hTiff = TiffOpen(
  217. FileName,
  218. &_TiffInfo,
  219. TRUE
  220. );
  221. if (!_hTiff) {
  222. PopUpMsg( L"Could not open TIFF file [%s]", FileName );
  223. return FALSE;
  224. }
  225. if ( (_TiffInfo.ImageWidth != 1728) ||
  226. (_TiffInfo.CompressionType != 4 ) ) {
  227. PopUpMsg( L"Not valid MS TIFF file\n" );
  228. TiffClose( _hTiff );
  229. return FALSE;
  230. }
  231. _TiffDataSize = _TiffInfo.ImageHeight * (_TiffInfo.ImageWidth / 8);
  232. _TiffData = (LPBYTE) VirtualAlloc(
  233. NULL,
  234. _TiffDataSize,
  235. MEM_COMMIT,
  236. PAGE_READWRITE
  237. );
  238. if (!_TiffData) {
  239. TiffClose( _hTiff );
  240. PopUpMsg( L"could allocate memory for TIFF data\n" );
  241. return FALSE;
  242. }
  243. hTiff = _hTiff;
  244. TiffInfo = _TiffInfo;
  245. TiffData = _TiffData;
  246. TiffDataSize = _TiffDataSize;
  247. TiffDataLinesAlloc = TiffInfo.ImageHeight;
  248. CurrPage = 1;
  249. ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, CurrPage );
  250. bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  251. bmi->bmiHeader.biWidth = TiffInfo.ImageWidth;
  252. bmi->bmiHeader.biHeight = - (INT) TiffInfo.ImageHeight;
  253. bmi->bmiHeader.biPlanes = 1;
  254. bmi->bmiHeader.biBitCount = 1;
  255. bmi->bmiHeader.biCompression = BI_RGB;
  256. bmi->bmiHeader.biSizeImage = 0;
  257. bmi->bmiHeader.biXPelsPerMeter = 7874;
  258. bmi->bmiHeader.biYPelsPerMeter = 7874;
  259. bmi->bmiHeader.biClrUsed = 0;
  260. bmi->bmiHeader.biClrImportant = 0;
  261. if (TiffInfo.PhotometricInterpretation) {
  262. bmi->bmiColors[0].rgbBlue = 0;
  263. bmi->bmiColors[0].rgbGreen = 0;
  264. bmi->bmiColors[0].rgbRed = 0;
  265. bmi->bmiColors[0].rgbReserved = 0;
  266. bmi->bmiColors[1].rgbBlue = 0xff;
  267. bmi->bmiColors[1].rgbGreen = 0xff;
  268. bmi->bmiColors[1].rgbRed = 0xff;
  269. bmi->bmiColors[1].rgbReserved = 0;
  270. } else {
  271. bmi->bmiColors[0].rgbBlue = 0xff;
  272. bmi->bmiColors[0].rgbGreen = 0xff;
  273. bmi->bmiColors[0].rgbRed = 0xff;
  274. bmi->bmiColors[0].rgbReserved = 0;
  275. bmi->bmiColors[1].rgbBlue = 0;
  276. bmi->bmiColors[1].rgbGreen = 0;
  277. bmi->bmiColors[1].rgbRed = 0;
  278. bmi->bmiColors[1].rgbReserved = 0;
  279. }
  280. OrigWidth = Width = TiffInfo.ImageWidth;
  281. OrigHeight = Height = TiffInfo.ImageHeight;
  282. TiffFileOpened = TRUE;
  283. return TRUE;
  284. }
  285. VOID
  286. FitRectToScreen(
  287. PRECT prc
  288. )
  289. {
  290. INT cxScreen;
  291. INT cyScreen;
  292. INT delta;
  293. cxScreen = GetSystemMetrics(SM_CXSCREEN);
  294. cyScreen = GetSystemMetrics(SM_CYSCREEN);
  295. if (prc->right > cxScreen) {
  296. delta = prc->right - prc->left;
  297. prc->right = cxScreen;
  298. prc->left = prc->right - delta;
  299. }
  300. if (prc->left < 0) {
  301. delta = prc->right - prc->left;
  302. prc->left = 0;
  303. prc->right = prc->left + delta;
  304. }
  305. if (prc->bottom > cyScreen) {
  306. delta = prc->bottom - prc->top;
  307. prc->bottom = cyScreen;
  308. prc->top = prc->bottom - delta;
  309. }
  310. if (prc->top < 0) {
  311. delta = prc->bottom - prc->top;
  312. prc->top = 0;
  313. prc->bottom = prc->top + delta;
  314. }
  315. }
  316. VOID
  317. CenterWindow(
  318. HWND hwnd,
  319. HWND hwndToCenterOver
  320. )
  321. {
  322. RECT rc;
  323. RECT rcOwner;
  324. RECT rcCenter;
  325. HWND hwndOwner;
  326. GetWindowRect( hwnd, &rc );
  327. if (hwndToCenterOver) {
  328. hwndOwner = hwndToCenterOver;
  329. GetClientRect( hwndOwner, &rcOwner );
  330. } else {
  331. hwndOwner = GetWindow( hwnd, GW_OWNER );
  332. if (!hwndOwner) {
  333. hwndOwner = GetDesktopWindow();
  334. }
  335. GetWindowRect( hwndOwner, &rcOwner );
  336. }
  337. //
  338. // Calculate the starting x,y for the new
  339. // window so that it would be centered.
  340. //
  341. rcCenter.left = rcOwner.left +
  342. (((rcOwner.right - rcOwner.left) -
  343. (rc.right - rc.left))
  344. / 2);
  345. rcCenter.top = rcOwner.top +
  346. (((rcOwner.bottom - rcOwner.top) -
  347. (rc.bottom - rc.top))
  348. / 2);
  349. rcCenter.right = rcCenter.left + (rc.right - rc.left);
  350. rcCenter.bottom = rcCenter.top + (rc.bottom - rc.top);
  351. FitRectToScreen( &rcCenter );
  352. SetWindowPos(hwnd, NULL, rcCenter.left, rcCenter.top, 0, 0,
  353. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  354. }
  355. LRESULT
  356. AskViewerDlgProc(
  357. HWND hwnd,
  358. UINT msg,
  359. WPARAM wParam,
  360. LPARAM lParam
  361. )
  362. {
  363. switch( msg ) {
  364. case WM_INITDIALOG:
  365. CenterWindow( hwnd, GetDesktopWindow() );
  366. break;
  367. case WM_COMMAND:
  368. switch( wParam ) {
  369. case IDOK:
  370. SetAskForViewerValue( !IsDlgButtonChecked( hwnd, IDC_DEFAULT_VIEWER ) == BST_CHECKED );
  371. EndDialog( hwnd, IDOK );
  372. break;
  373. case IDCANCEL:
  374. SetAskForViewerValue( !IsDlgButtonChecked( hwnd, IDC_DEFAULT_VIEWER ) == BST_CHECKED );
  375. EndDialog( hwnd, IDCANCEL );
  376. break;
  377. }
  378. break;
  379. }
  380. return FALSE;
  381. }
  382. void
  383. MoveCoolbar(
  384. DWORD HowAlign
  385. )
  386. {
  387. RECT rc;
  388. RECT rcCoolbar;
  389. int x;
  390. int y;
  391. int cx;
  392. int cy;
  393. GetClientRect( hwndMain, &rc );
  394. GetWindowRect( hwndCoolbar, &rcCoolbar );
  395. switch( HowAlign ) {
  396. default:
  397. case TOP:
  398. x = 0;
  399. y = 0;
  400. cx = rc.right - rc.left;
  401. cy = rc.bottom - rc.top;
  402. break;
  403. case LEFT:
  404. x = 0;
  405. y = 0;
  406. cx = rcCoolbar.right - rcCoolbar.left;
  407. cy = rc.bottom - rc.top;
  408. break;
  409. case BOTTOM:
  410. x = 0;
  411. y = rc.bottom - (rcCoolbar.bottom - rcCoolbar.top);
  412. cx = rc.right - rc.left;
  413. cy = rcCoolbar.bottom - rcCoolbar.top;
  414. break;
  415. case RIGHT:
  416. x = rc.right - (rcCoolbar.right - rcCoolbar.left);
  417. y = 0;
  418. cx = rcCoolbar.right - rcCoolbar.left;
  419. cy = rc.bottom - rc.top;
  420. break;
  421. }
  422. MoveWindow( hwndCoolbar, x, y, cx, cy, TRUE );
  423. }
  424. VOID
  425. LoadBackgroundBitmap(
  426. VOID
  427. )
  428. {
  429. COLORREF clrFace;
  430. HBITMAP hbmSave;
  431. UINT n;
  432. UINT i;
  433. RGBQUAD rgbTable[256];
  434. RGBQUAD rgbFace;
  435. HDC hdc;
  436. if (hBitmapBackground) {
  437. DeleteObject( hBitmapBackground );
  438. }
  439. hBitmapBackground = (HBITMAP) LoadImage(
  440. hInstance,
  441. MAKEINTRESOURCE(IDB_COOLBAR),
  442. IMAGE_BITMAP,
  443. 0,
  444. 0,
  445. LR_DEFAULTSIZE | LR_CREATEDIBSECTION
  446. );
  447. hdc = CreateCompatibleDC(NULL);
  448. clrFace = GetSysColor(COLOR_BTNFACE);
  449. if (clrFace != RGB(192,192,192)) {
  450. hbmSave = (HBITMAP) SelectObject( hdc, hBitmapBackground );
  451. n = GetDIBColorTable(hdc, 0, 256, rgbTable);
  452. rgbFace.rgbRed = GetRValue(clrFace);
  453. rgbFace.rgbGreen = GetGValue(clrFace);
  454. rgbFace.rgbBlue = GetBValue(clrFace);
  455. for (i = 0; i < n; i++)
  456. {
  457. rgbTable[i].rgbRed = (rgbTable[i].rgbRed * rgbFace.rgbRed ) / 192;
  458. rgbTable[i].rgbGreen = (rgbTable[i].rgbGreen * rgbFace.rgbGreen) / 192;
  459. rgbTable[i].rgbBlue = (rgbTable[i].rgbBlue * rgbFace.rgbBlue ) / 192;
  460. }
  461. SetDIBColorTable(hdc, 0, n, rgbTable);
  462. SelectObject(hdc, hbmSave);
  463. }
  464. DeleteDC( hdc );
  465. }
  466. VOID
  467. SetBackground(
  468. VOID
  469. )
  470. {
  471. REBARBANDINFO rbbi;
  472. DWORD fMask;
  473. LoadBackgroundBitmap();
  474. if (hBitmapBackground) {
  475. fMask = RBBIM_BACKGROUND;
  476. rbbi.hbmBack = hBitmapBackground;
  477. } else {
  478. fMask = RBBIM_BACKGROUND | RBBIM_COLORS;
  479. rbbi.hbmBack = NULL;
  480. rbbi.clrFore = GetSysColor(COLOR_BTNTEXT);
  481. rbbi.clrBack = GetSysColor(COLOR_BTNFACE);
  482. }
  483. rbbi.cbSize = sizeof(REBARBANDINFO);
  484. rbbi.fMask = RBBIM_ID | RBBIM_CHILD;
  485. if (SendMessage( hwndCoolbar, RB_GETBANDINFO, 0, (LPARAM) &rbbi )) {
  486. rbbi.fMask = fMask;
  487. SendMessage( hwndCoolbar, RB_SETBANDINFO, 0, (LPARAM) &rbbi );
  488. InvalidateRect( rbbi.hwndChild, NULL, TRUE );
  489. }
  490. }
  491. int
  492. WINAPI
  493. wWinMain(
  494. HINSTANCE hInst,
  495. HINSTANCE hPrevInstance,
  496. LPWSTR lpCmdLine,
  497. int nShowCmd
  498. )
  499. /*++
  500. Routine Description:
  501. Main entry point for the TIFF image viewer.
  502. Arguments:
  503. hInstance - Instance handle
  504. hPrevInstance - Not used
  505. lpCmdLine - Command line arguments
  506. nShowCmd - How to show the window
  507. Return Value:
  508. Return code, zero for success.
  509. --*/
  510. {
  511. LPWSTR *argv;
  512. DWORD argc;
  513. WNDCLASS wc;
  514. MSG msg;
  515. RECT rect;
  516. DWORD i;
  517. HANDLE hThread;
  518. LOGBRUSH lb;
  519. RECT rc;
  520. TBADDBITMAP tbab;
  521. INITCOMMONCONTROLSEX iccex;
  522. REBARBANDINFO rbbi;
  523. LRESULT lButtonSize;
  524. hInstance = hInst;
  525. //
  526. // general init code
  527. //
  528. HeapInitialize(NULL,NULL,NULL,0);
  529. iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  530. iccex.dwICC = ICC_COOL_CLASSES;
  531. InitCommonControlsEx( &iccex );
  532. FaxTiffInitialize();
  533. //
  534. // process the command line
  535. //
  536. argv = CommandLineToArgvW( GetCommandLine(), &argc );
  537. for (i=1; i<argc; i++) {
  538. if (argv[i][0] == L'-' || argv[i][0] == L'/') {
  539. switch (towlower(argv[i][1])) {
  540. case L'p':
  541. if (towlower(argv[i][2]) == L't') {
  542. hThread = PrintTiffFile( NULL, argv[i+1], argv[i+2] );
  543. } else {
  544. hThread = PrintTiffFile( NULL, argv[i+1], NULL );
  545. }
  546. if (hThread) {
  547. WaitForSingleObject( hThread, INFINITE );
  548. }
  549. return 0;
  550. default:
  551. break;
  552. }
  553. } else {
  554. //
  555. // must be a file name for viewing
  556. //
  557. wcscpy( TiffFileName, argv[i] );
  558. }
  559. }
  560. if ((!IsFaxViewerDefaultViewer()) && IsItOkToAskForDefault()) {
  561. int Answer = DialogBox( hInstance, MAKEINTRESOURCE(IDD_VIEWER), NULL, AskViewerDlgProc );
  562. if (Answer == IDOK) {
  563. MakeFaxViewerDefaultViewer();
  564. }
  565. }
  566. CxScreen = GetSystemMetrics( SM_CXSCREEN );
  567. CyScreen = GetSystemMetrics( SM_CYSCREEN );
  568. ScrollWidth = GetSystemMetrics( SM_CYVSCROLL );
  569. ScrollHeight = GetSystemMetrics( SM_CYHSCROLL );
  570. CurrPage = 1;
  571. wc.style = CS_HREDRAW | CS_VREDRAW;
  572. wc.lpfnWndProc = (WNDPROC)WndProc;
  573. wc.cbClsExtra = 0;
  574. wc.cbWndExtra = 0;
  575. wc.hInstance = hInstance;
  576. wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
  577. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  578. wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
  579. wc.lpszMenuName = MAKEINTRESOURCE( FAXVIEW );
  580. wc.lpszClassName = L"FaxView";
  581. if (!RegisterClass(&wc)) {
  582. return FALSE;
  583. }
  584. lb.lbStyle = BS_SOLID;
  585. lb.lbColor = RGB( 221,232,23 );
  586. lb.lbHatch = 0;
  587. wc.lpfnWndProc = (WNDPROC)ChildWndProc;
  588. wc.hIcon = NULL;
  589. wc.hCursor = LoadCursor(NULL, IDC_CROSS);
  590. wc.lpszMenuName = NULL;
  591. wc.lpszClassName = L"FaxViewChild";
  592. if (!RegisterClass(&wc)) {
  593. return FALSE;
  594. }
  595. hwndMain = CreateWindow(
  596. L"FaxView", // window class name
  597. L"FaxView", // window caption
  598. WS_OVERLAPPEDWINDOW, // window style
  599. CW_USEDEFAULT, // initial x position
  600. CW_USEDEFAULT, // initial y position
  601. CW_USEDEFAULT, // initial x size
  602. CW_USEDEFAULT, // initial y size
  603. NULL, // parent window handle
  604. NULL, // window menu handle
  605. hInstance, // program instance handle
  606. NULL // creation parameters
  607. );
  608. if (!hwndMain) {
  609. return 0;
  610. }
  611. hMenu = GetMenu( hwndMain );
  612. hMenuZoom = GetSubMenu( GetSubMenu( hMenu, 1 ), 3 );
  613. Hourglass = LoadCursor( NULL, IDC_WAIT );
  614. if (!Hourglass) {
  615. DebugPrint(( L"LoadCursor() failed for IDC_WAIT, ec=%d", GetLastError() ));
  616. }
  617. //
  618. // create the coolbar
  619. //
  620. hwndCoolbar = CreateWindowEx(
  621. WS_EX_TOOLWINDOW,
  622. REBARCLASSNAME,
  623. NULL,
  624. WS_VISIBLE |
  625. WS_BORDER |
  626. WS_CHILD |
  627. WS_CLIPCHILDREN |
  628. WS_CLIPSIBLINGS |
  629. RBS_TOOLTIPS |
  630. RBS_BANDBORDERS |
  631. CCS_NODIVIDER |
  632. CCS_NOPARENTALIGN,
  633. 0,
  634. 0,
  635. 200,
  636. 100,
  637. hwndMain,
  638. (HMENU) IDM_COOLBAR,
  639. hInstance,
  640. NULL
  641. );
  642. if (!hwndCoolbar) {
  643. return 0;
  644. }
  645. //
  646. // create and populate the toolbar
  647. //
  648. hwndToolbar = CreateWindowEx(
  649. WS_EX_TOOLWINDOW,
  650. TOOLBARCLASSNAME,
  651. NULL,
  652. WS_CHILD | TBSTYLE_FLAT | CCS_ADJUSTABLE | CCS_NODIVIDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NOPARENTALIGN,
  653. 0,
  654. 0,
  655. 0,
  656. 0,
  657. hwndCoolbar,
  658. (HMENU) IDM_TOOLBAR,
  659. hInstance,
  660. NULL
  661. );
  662. SendMessage( hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0 );
  663. SendMessage( hwndToolbar, TB_SETMAXTEXTROWS, 2, 0 );
  664. SendMessage( hwndToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24,24) );
  665. tbab.hInst = hInstance;
  666. tbab.nID = IDB_OPEN_BIG;
  667. SendMessage( hwndToolbar, TB_ADDBITMAP, 1, (LPARAM) &tbab );
  668. tbab.nID = IDB_PRINT_BIG;
  669. SendMessage( hwndToolbar, TB_ADDBITMAP, 1, (LPARAM) &tbab );
  670. tbab.nID = IDB_ZOOM_BIG;
  671. SendMessage( hwndToolbar, TB_ADDBITMAP, 1, (LPARAM) &tbab );
  672. tbab.nID = IDB_HELP_BIG;
  673. SendMessage( hwndToolbar, TB_ADDBITMAP, 1, (LPARAM) &tbab );
  674. SendMessage( hwndToolbar, TB_ADDSTRING, 0, (LPARAM) L"Open\0Print\0Zoom\0Help\0\0" );
  675. SendMessage( hwndToolbar, TB_ADDBUTTONS, sizeof(TbButton)/sizeof(TBBUTTON), (LPARAM)&TbButton );
  676. SendMessage( hwndToolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(50,200) );
  677. ShowWindow( hwndToolbar, SW_SHOW );
  678. //
  679. // add the toolbar to the coolbar
  680. //
  681. lButtonSize = SendMessage( hwndToolbar, TB_GETBUTTONSIZE, 0, 0 );
  682. ZeroMemory( &rbbi, sizeof(rbbi) );
  683. rbbi.cbSize = sizeof(REBARBANDINFO);
  684. rbbi.fMask = RBBIM_CHILD |
  685. RBBIM_CHILDSIZE |
  686. RBBIM_ID |
  687. RBBIM_STYLE |
  688. RBBIM_COLORS ;
  689. rbbi.cxMinChild = LOWORD(lButtonSize);
  690. rbbi.cyMinChild = HIWORD(lButtonSize);
  691. rbbi.clrFore = GetSysColor(COLOR_BTNTEXT);
  692. rbbi.clrBack = GetSysColor(COLOR_BTNFACE);
  693. rbbi.fStyle = RBBS_CHILDEDGE | RBBS_FIXEDBMP;
  694. rbbi.wID = IDM_TOOLBAR;
  695. rbbi.hwndChild = hwndToolbar;
  696. rbbi.lpText = NULL;
  697. rbbi.hbmBack = NULL;
  698. rbbi.iImage = 0;
  699. SendMessage( hwndCoolbar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbbi );
  700. SetBackground();
  701. MoveCoolbar( TOP );
  702. GetWindowRect( hwndCoolbar, &rc );
  703. ToolbarHeight = rc.bottom - rc.top - 1;
  704. hwndStatusbar = CreateStatusWindow(
  705. WS_CHILD | WS_VISIBLE | WS_BORDER,
  706. L"Fax Viewer",
  707. hwndMain,
  708. IDM_STATUSBAR
  709. );
  710. GetWindowRect( hwndStatusbar, &rect );
  711. StatusbarHeight = rect.bottom - rect.top;
  712. InitializeStatusBar( hwndMain );
  713. if (TiffFileName[0]) {
  714. PostMessage( hwndMain, WM_OPEN_FILE, 0, (LPARAM) TiffFileName );
  715. }
  716. GetClientRect( hwndMain, &rc );
  717. hwndView = CreateWindow(
  718. L"FaxViewChild", // window class name
  719. NULL, // window caption
  720. WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, // window style
  721. rc.left, // initial x position
  722. rc.top + ToolbarHeight + SEPHEIGHT, // initial y position
  723. rc.right - rc.left, // initial x size
  724. rc.bottom - rc.top - ToolbarHeight - SEPHEIGHT - StatusbarHeight, // initial y size
  725. hwndMain, // parent window handle
  726. NULL, // window menu handle
  727. hInstance, // program instance handle
  728. NULL // creation parameters
  729. );
  730. if (!hwndView) {
  731. return 0;
  732. }
  733. hwndTooltip = CreateWindowEx(
  734. WS_EX_TOOLWINDOW,
  735. TOOLTIPS_CLASS,
  736. NULL,
  737. WS_CHILD,
  738. 0,
  739. 0,
  740. 0,
  741. 0,
  742. hwndView,
  743. (HMENU) IDM_TOOLTIP,
  744. hInstance,
  745. NULL
  746. );
  747. if (!hwndTooltip) {
  748. return 0;
  749. }
  750. ShowWindow( hwndMain, SW_SHOWNORMAL );
  751. ShowWindow( hwndView, SW_SHOWNORMAL );
  752. UpdateWindow( hwndMain );
  753. UpdateWindow( hwndView );
  754. InvalidateRect( hwndView, NULL, TRUE );
  755. while (GetMessage (&msg, NULL, 0, 0)) {
  756. TranslateMessage (&msg) ;
  757. DispatchMessage (&msg) ;
  758. }
  759. return 0;
  760. }
  761. BOOL
  762. ReadTiffData(
  763. HANDLE hTiff,
  764. LPBYTE *TiffData,
  765. DWORD Width,
  766. LPDWORD TiffDataLinesAlloc,
  767. DWORD PageNumber
  768. )
  769. {
  770. DWORD Lines = 0;
  771. TiffSeekToPage( hTiff, PageNumber, FILLORDER_LSB2MSB );
  772. TiffUncompressMmrPage( hTiff, (LPDWORD) *TiffData, &Lines );
  773. if (Lines > *TiffDataLinesAlloc) {
  774. *TiffDataLinesAlloc = Lines;
  775. VirtualFree( *TiffData, 0, MEM_RELEASE );
  776. *TiffData = (LPBYTE) VirtualAlloc(
  777. NULL,
  778. Lines * (Width / 8),
  779. MEM_COMMIT,
  780. PAGE_READWRITE
  781. );
  782. if (!*TiffData) {
  783. return FALSE;
  784. }
  785. }
  786. if (!TiffUncompressMmrPage( hTiff, (LPDWORD) *TiffData, &Lines )) {
  787. return FALSE;
  788. }
  789. EnableMenuItem( hMenu, IDM_PAGE_UP, PageNumber == 1 ? MF_GRAYED : MF_ENABLED );
  790. return TRUE;
  791. }
  792. VOID
  793. PopUpMsg(
  794. LPWSTR format,
  795. ...
  796. )
  797. /*++
  798. Routine Description:
  799. Pops up a message box to indicate an error.
  800. Arguments:
  801. format - Format string
  802. ... - Other arguments
  803. Return Value:
  804. None.
  805. --*/
  806. {
  807. WCHAR buf[1024];
  808. va_list arg_ptr;
  809. va_start( arg_ptr, format );
  810. _vsnwprintf( buf, sizeof(buf), format, arg_ptr );
  811. va_end( arg_ptr );
  812. MessageBox(
  813. NULL,
  814. buf,
  815. L"FaxView",
  816. MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION
  817. );
  818. }
  819. VOID
  820. ChangeTitle(
  821. HWND hwnd,
  822. LPWSTR FileName
  823. )
  824. /*++
  825. Routine Description:
  826. Changes the title text of the window.
  827. Arguments:
  828. hwnd - Window handle
  829. Return Value:
  830. None.
  831. --*/
  832. {
  833. LPWSTR p;
  834. WCHAR WindowTitle[128];
  835. p = wcsrchr( FileName, L'\\' );
  836. if (p) {
  837. FileName = p + 1;
  838. }
  839. if (TiffFileName[0]) {
  840. swprintf( WindowTitle, L"FaxView - %s Page %d of %d", FileName, CurrPage, TiffInfo.PageCount );
  841. } else {
  842. swprintf( WindowTitle, L"FaxView" );
  843. }
  844. SetWindowText( hwnd, WindowTitle );
  845. }
  846. VOID
  847. UpdateStatusBar(
  848. LPWSTR lpszStatusString,
  849. WORD partNumber,
  850. WORD displayFlags
  851. )
  852. {
  853. SendMessage(
  854. hwndStatusbar,
  855. SB_SETTEXT,
  856. partNumber | displayFlags,
  857. (LPARAM)lpszStatusString
  858. );
  859. }
  860. VOID
  861. InitializeStatusBar(
  862. HWND hwnd
  863. )
  864. {
  865. UpdateStatusBar( L"Fax Viewer", 0, 0 );
  866. }
  867. LRESULT
  868. WndProc(
  869. HWND hwnd,
  870. UINT message,
  871. WPARAM wParam,
  872. LPARAM lParam
  873. )
  874. /*++
  875. Routine Description:
  876. Window procedure for the TIFF image viewer main window.
  877. Arguments:
  878. hwnd - Window handle
  879. message - message identifier
  880. wParam - Parameter
  881. lParam - Parameter
  882. Return Value:
  883. Return result, zero for success.
  884. --*/
  885. {
  886. HDC hdc;
  887. RECT rc;
  888. HCURSOR OldCursor;
  889. BOOL ReOpen;
  890. PAINTSTRUCT ps;
  891. LPWSTR p;
  892. WCHAR FileName[MAX_PATH*2];
  893. switch (message) {
  894. case WM_CREATE:
  895. hmenuFrame = GetMenu( hwnd );
  896. QueryWindowPlacement( hwnd );
  897. return 0;
  898. case WM_PAINT:
  899. GetClientRect( hwnd, &rc );
  900. rc.top += ToolbarHeight;
  901. rc.bottom = rc.top + SEPHEIGHT;
  902. hdc = BeginPaint( hwnd, &ps );
  903. DrawEdge( hdc, &rc, EDGE_RAISED, BF_TOP | BF_BOTTOM | BF_MIDDLE );
  904. EndPaint( hwnd, &ps );
  905. return 0;
  906. case WM_OPEN_FILE:
  907. ReOpen = FALSE;
  908. wcscpy( FileName, (LPWSTR) lParam );
  909. goto open_file;
  910. return 0;
  911. case WM_NOTIFY:
  912. if (((LPNMHDR)lParam)->code == TBN_DROPDOWN) {
  913. SendMessage( hwndToolbar, TB_GETRECT, IDM_ZOOM, (LPARAM)&rc );
  914. rc.top = rc.bottom;
  915. MapWindowPoints( hwndToolbar, HWND_DESKTOP, (POINT *)&rc, 2 );
  916. TrackPopupMenu( hMenuZoom, TPM_LEFTALIGN | TPM_LEFTBUTTON, rc.left, rc.top, 0, hwnd, NULL );
  917. }
  918. return 0;
  919. case WM_COMMAND:
  920. if (HIWORD(wParam) == 0) {
  921. switch( wParam ) {
  922. case IDM_FILEOPEN:
  923. ReOpen = TiffFileOpened;
  924. //
  925. // ask the user to choose a file name
  926. //
  927. if (!BrowseForFileName( hwnd, FileName, L"tif", L"Fax Image Files", LastDir )) {
  928. return 0;
  929. }
  930. open_file:
  931. if (!OpenTiffFile( FileName, hwnd )) {
  932. return 0;
  933. }
  934. //
  935. // update the last directory name
  936. //
  937. p = wcsrchr( FileName, L'\\' );
  938. if (p) {
  939. wcscpy( LastDir, FileName );
  940. p = wcsrchr( LastDir, L'\\' );
  941. if (p) {
  942. *p = 0;
  943. }
  944. }
  945. wcscpy( TiffFileName, FileName );
  946. OldCursor = SetCursor( Hourglass );
  947. if (ReOpen) {
  948. TiffFileOpened = FALSE;
  949. TiffClose( hTiff );
  950. VirtualFree( TiffData, 0, MEM_RELEASE );
  951. TiffData = NULL;
  952. hTiff = NULL;
  953. Width = 0;
  954. Height = 0;
  955. OrigWidth = 0;
  956. OrigHeight = 0;
  957. TiffDataSize = 0;
  958. SendMessage( hwndView, WM_VIEW_CLOSE, 0, 0 );
  959. }
  960. ChangeTitle( hwnd, TiffFileName );
  961. SendMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  962. SetCursor( OldCursor );
  963. EnableMenuItem( hMenu, IDM_CLOSE, MF_ENABLED );
  964. EnableMenuItem( hMenu, IDM_PRINT, MF_ENABLED );
  965. EnableMenuItem( hMenu, IDM_PRINT_SETUP, MF_ENABLED );
  966. EnableMenuItem( hMenu, IDM_ZOOM, MF_ENABLED );
  967. EnableMenuItem( hMenu, IDM_PAGE_UP, MF_GRAYED );
  968. if (TiffInfo.PageCount > 1) {
  969. EnableMenuItem( hMenu, IDM_PAGE_DOWN, MF_ENABLED );
  970. }
  971. SendMessage( hwndToolbar, TB_SETSTATE, IDM_PRINT, (LPARAM) MAKELONG(TBSTATE_ENABLED, 0) );
  972. SendMessage( hwndToolbar, TB_SETSTATE, IDM_ZOOM, (LPARAM) MAKELONG(TBSTATE_ENABLED, 0) );
  973. return 0;
  974. case IDM_ZOOM_100:
  975. case IDM_ZOOM_90:
  976. case IDM_ZOOM_80:
  977. case IDM_ZOOM_70:
  978. case IDM_ZOOM_60:
  979. case IDM_ZOOM_50:
  980. case IDM_ZOOM_40:
  981. case IDM_ZOOM_30:
  982. case IDM_ZOOM_20:
  983. case IDM_ZOOM_10:
  984. CheckMenuItem( hMenuZoom, CurrZoom+IDM_ZOOM_100, MF_UNCHECKED );
  985. CheckMenuItem( hMenuZoom, wParam, MF_CHECKED );
  986. CurrZoom = wParam - IDM_ZOOM_100;
  987. SendMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  988. return 0;
  989. case IDM_PAGE_UP:
  990. if (CurrPage == 1) {
  991. MessageBeep( MB_ICONEXCLAMATION );
  992. return 0;
  993. }
  994. ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, --CurrPage );
  995. ChangeTitle( hwnd, TiffFileName );
  996. SendMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  997. return 0;
  998. case IDM_PAGE_DOWN:
  999. if (CurrPage == TiffInfo.PageCount) {
  1000. MessageBeep( MB_ICONEXCLAMATION );
  1001. return 0;
  1002. }
  1003. ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, ++CurrPage );
  1004. ChangeTitle( hwnd, TiffFileName );
  1005. SendMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  1006. return 0;
  1007. case IDM_PRINT_SETUP:
  1008. PrintSetup( hwnd );
  1009. return 0;
  1010. case IDM_PRINT:
  1011. PrintTiffFile( hwnd, TiffFileName, NULL );
  1012. return 0;
  1013. case IDM_CLOSE:
  1014. TiffFileOpened = FALSE;
  1015. TiffClose( hTiff );
  1016. VirtualFree( TiffData, 0, MEM_RELEASE );
  1017. TiffData = NULL;
  1018. hTiff = NULL;
  1019. Width = 0;
  1020. Height = 0;
  1021. OrigWidth = 0;
  1022. OrigHeight = 0;
  1023. TiffDataSize = 0;
  1024. TiffFileName[0] = 0;
  1025. ChangeTitle( hwnd, TiffFileName );
  1026. SendMessage( hwndView, WM_VIEW_CLOSE, 0, 0 );
  1027. EnableMenuItem( hMenu, IDM_CLOSE, MF_GRAYED );
  1028. EnableMenuItem( hMenu, IDM_PRINT, MF_GRAYED );
  1029. EnableMenuItem( hMenu, IDM_PRINT_SETUP, MF_GRAYED );
  1030. EnableMenuItem( hMenu, IDM_PAGE_UP, MF_GRAYED );
  1031. EnableMenuItem( hMenu, IDM_PAGE_DOWN, MF_GRAYED );
  1032. EnableMenuItem( hMenu, IDM_ZOOM, MF_GRAYED );
  1033. SendMessage( hwndToolbar, TB_SETSTATE, IDM_PRINT, (LPARAM) MAKELONG(TBSTATE_INDETERMINATE, 0) );
  1034. SendMessage( hwndToolbar, TB_SETSTATE, IDM_ZOOM, (LPARAM) MAKELONG(TBSTATE_INDETERMINATE, 0) );
  1035. return 0;
  1036. case IDM_EXIT:
  1037. PostQuitMessage( 0 );
  1038. return 0;
  1039. case IDM_HELP:
  1040. WinHelp(hwnd, TEXT( "faxview.HLP" ), HELP_FINDER, 0L);
  1041. return 0;
  1042. case IDM_ABOUT:
  1043. ShellAbout( hwnd, L"Fax Viewer", NULL, NULL );
  1044. break;
  1045. }
  1046. }
  1047. return 0;
  1048. case WM_SIZE:
  1049. MoveCoolbar( TOP );
  1050. SendMessage( hwndToolbar, message, wParam, lParam );
  1051. SendMessage( hwndStatusbar, message, wParam, lParam );
  1052. InitializeStatusBar( hwnd );
  1053. CyClient = HIWORD(lParam) - ToolbarHeight - SEPHEIGHT - StatusbarHeight;
  1054. CxClient = LOWORD(lParam);
  1055. //
  1056. // resize the view window
  1057. //
  1058. GetClientRect( hwnd, &rc );
  1059. MoveWindow(
  1060. hwndView,
  1061. rc.left,
  1062. rc.top+ToolbarHeight+SEPHEIGHT,
  1063. CxClient,
  1064. CyClient,
  1065. TRUE
  1066. );
  1067. return 0;
  1068. case WM_KEYDOWN:
  1069. switch( wParam ) {
  1070. case VK_NEXT:
  1071. if (GetKeyState( VK_CONTROL ) & 0x8000) {
  1072. SendMessage( hwnd, WM_COMMAND, IDM_PAGE_DOWN, 0 );
  1073. } else {
  1074. SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_PAGEDOWN,0), 0 );
  1075. }
  1076. break;
  1077. case VK_PRIOR:
  1078. if (GetKeyState( VK_CONTROL ) & 0x8000) {
  1079. SendMessage( hwnd, WM_COMMAND, IDM_PAGE_UP, 0 );
  1080. } else {
  1081. SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_PAGEUP,0), 0 );
  1082. }
  1083. break;
  1084. case VK_END:
  1085. SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_BOTTOM,0), 0 );
  1086. break;
  1087. case VK_HOME:
  1088. SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_TOP,0), 0 );
  1089. break;
  1090. case VK_LEFT:
  1091. SendMessage( hwndView, WM_HSCROLL, MAKELONG(SB_LINELEFT,0), 0 );
  1092. break;
  1093. case VK_RIGHT:
  1094. SendMessage( hwndView, WM_HSCROLL, MAKELONG(SB_LINERIGHT,0), 0 );
  1095. break;
  1096. case VK_UP:
  1097. SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_LINEUP,0), 0 );
  1098. break;
  1099. case VK_DOWN:
  1100. SendMessage( hwndView, WM_VSCROLL, MAKELONG(SB_LINEDOWN,0), 0 );
  1101. break;
  1102. case VK_F4:
  1103. SendMessage( hwnd, WM_COMMAND, IDM_FILEOPEN, 0 );
  1104. break;
  1105. case VK_F1:
  1106. SendMessage( hwnd, WM_COMMAND, IDM_HELP, 0 );
  1107. break;
  1108. }
  1109. return 0;
  1110. case WM_SYSCOLORCHANGE:
  1111. SendMessage( hwndCoolbar, message, wParam, lParam );
  1112. SetBackground();
  1113. return 0;
  1114. case WM_DESTROY:
  1115. SaveWindowPlacement( hwnd );
  1116. PostQuitMessage( 0 );
  1117. return 0;
  1118. }
  1119. return DefWindowProc( hwnd, message, wParam, lParam );
  1120. }
  1121. VOID
  1122. UpdateScrollInfo(
  1123. HWND hwnd
  1124. )
  1125. {
  1126. SCROLLINFO si;
  1127. //
  1128. // set the vertical scroll amounts for pages & lines
  1129. //
  1130. if (TiffInfo.PageCount) {
  1131. VScrollMax = TiffInfo.PageCount * Height;
  1132. VScrollPage = Height;
  1133. VScrollLine = VScrollPage / 10;
  1134. HScrollLine = TiffInfo.ImageWidth / 10;
  1135. } else {
  1136. VScrollMax = 0;
  1137. VScrollPage = 0;
  1138. VScrollLine = 0;
  1139. }
  1140. si.cbSize = sizeof(SCROLLINFO);
  1141. si.fMask = SIF_RANGE;
  1142. GetScrollInfo( hwnd, SB_VERT, &si );
  1143. si.cbSize = sizeof(SCROLLINFO);
  1144. si.fMask = SIF_RANGE;
  1145. si.nMin = 0;
  1146. si.nMax = VScrollMax;
  1147. si.nPage = CyClient;
  1148. SetScrollInfo( hwnd, SB_VERT, &si, TRUE );
  1149. si.cbSize = sizeof(SCROLLINFO);
  1150. si.fMask = SIF_RANGE;
  1151. GetScrollInfo( hwnd, SB_HORZ, &si );
  1152. HScrollMax = Width - CxClient;
  1153. si.cbSize = sizeof(SCROLLINFO);
  1154. si.fMask = SIF_RANGE;
  1155. si.nMin = 0;
  1156. si.nMax = HScrollMax;
  1157. si.nPage = CxClient;
  1158. SetScrollInfo( hwnd, SB_HORZ, &si, TRUE );
  1159. }
  1160. DWORD
  1161. ScrollPosToPage(
  1162. DWORD ScrollPos
  1163. )
  1164. {
  1165. DWORD Page = 0;
  1166. Page = ScrollPos / VScrollPage;
  1167. Page = Page + (((ScrollPos % VScrollPage) > 0) ? 1 : 0);
  1168. return Page == 0 ? 1 : Page;
  1169. }
  1170. VOID
  1171. ScrollViewVertically(
  1172. HWND hwnd,
  1173. INT ScrollCode,
  1174. INT Position
  1175. )
  1176. {
  1177. INT OldScrollPos;
  1178. RECT rcClip;
  1179. INT Delta;
  1180. SCROLLINFO si;
  1181. DWORD NewPage;
  1182. DWORD Remaining;
  1183. OldScrollPos = VscrollPos;
  1184. if (ScrollCode == SB_LINEUP || ScrollCode == SB_LINEDOWN) {
  1185. if (ScrollCode == SB_LINEUP) {
  1186. VscrollPos -= VScrollLine;
  1187. } else {
  1188. VscrollPos += VScrollLine;
  1189. }
  1190. line_scroll:
  1191. VscrollPos = max( 0, min( VscrollPos, (int) VScrollMax ) );
  1192. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1193. Delta = VscrollPos - OldScrollPos;
  1194. if (Delta == 0) {
  1195. MessageBeep( MB_ICONASTERISK );
  1196. return;
  1197. } else if (Delta > 0) {
  1198. if (VscrollPos < (INT)VScrollPage) {
  1199. Remaining = VScrollPage - VscrollPos;
  1200. } else if (VscrollPos % VScrollPage == 0) {
  1201. Remaining = 0;
  1202. } else {
  1203. Remaining = TiffInfo.ImageHeight - (VscrollPos % VScrollPage);
  1204. }
  1205. if (Remaining < CyClient) {
  1206. VscrollPos -= (CyClient - Remaining);
  1207. Delta -= (CyClient - Remaining);
  1208. if (Delta == 0) {
  1209. //
  1210. // advance to the next page
  1211. //
  1212. if (CurrPage == TiffInfo.PageCount) {
  1213. MessageBeep( MB_ICONASTERISK );
  1214. VscrollPos = OldScrollPos;
  1215. return;
  1216. }
  1217. ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, ++CurrPage );
  1218. ChangeTitle( hwndMain, TiffFileName );
  1219. VscrollPos = VScrollPage*(CurrPage-1);
  1220. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1221. PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  1222. return;
  1223. }
  1224. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1225. }
  1226. GetClientRect( hwnd, &rcClip );
  1227. ScrollWindow( hwnd, 0, -Delta, NULL, &rcClip );
  1228. } else {
  1229. if (OldScrollPos % VScrollPage == 0) {
  1230. //
  1231. // advance to the previous page
  1232. //
  1233. if (CurrPage == 1) {
  1234. MessageBeep( MB_ICONASTERISK );
  1235. return;
  1236. }
  1237. ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, --CurrPage );
  1238. ChangeTitle( hwndMain, TiffFileName );
  1239. VscrollPos = VScrollPage * (CurrPage - 1) + TiffInfo.ImageHeight - CyClient;
  1240. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1241. PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  1242. return;
  1243. }
  1244. if (ScrollPosToPage( VscrollPos ) != CurrPage) {
  1245. //
  1246. // the file was positioned just below the top
  1247. // of the previous page, so lets align to the beginning
  1248. // of the current page
  1249. //
  1250. Remaining = -((INT)OldScrollPos - ((INT)CurrPage - 1) * (INT)TiffInfo.ImageHeight);
  1251. VscrollPos -= Delta - Remaining;
  1252. Delta = Remaining;
  1253. }
  1254. GetClientRect( hwnd, &rcClip );
  1255. ScrollWindow( hwnd, 0, -Delta, NULL, &rcClip );
  1256. }
  1257. return;
  1258. }
  1259. if (ScrollCode == SB_THUMBTRACK) {
  1260. if (ScrollPosTrack == -1) {
  1261. ScrollPosTrack = VscrollPos;
  1262. }
  1263. VscrollPos = max( 0, min( Position, (int) VScrollMax ) );
  1264. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1265. return;
  1266. }
  1267. if (ScrollCode == SB_ENDSCROLL && ScrollPosTrack != -1) {
  1268. si.cbSize = sizeof(SCROLLINFO);
  1269. si.fMask = SIF_POS;
  1270. GetScrollInfo( hwnd, SB_VERT, &si );
  1271. VscrollPos = si.nPos;
  1272. Delta = VscrollPos - ScrollPosTrack;
  1273. ScrollPosTrack = -1;
  1274. NewPage = ScrollPosToPage( VscrollPos );
  1275. if (NewPage != CurrPage) {
  1276. //
  1277. // the user changed pages
  1278. //
  1279. CurrPage = NewPage;
  1280. ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, CurrPage );
  1281. ChangeTitle( hwndMain, TiffFileName );
  1282. VscrollPos = VScrollPage*(CurrPage-1);
  1283. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1284. PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  1285. return;
  1286. } else {
  1287. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1288. if (Delta != 0) {
  1289. GetClientRect( hwnd, &rcClip );
  1290. ScrollWindow( hwnd, 0, -Delta, NULL, &rcClip );
  1291. }
  1292. return;
  1293. }
  1294. return;
  1295. }
  1296. if (ScrollCode == SB_PAGEDOWN) {
  1297. VscrollPos += CyClient;
  1298. goto line_scroll;
  1299. return;
  1300. }
  1301. if (ScrollCode == SB_PAGEUP) {
  1302. VscrollPos -= CyClient;
  1303. goto line_scroll;
  1304. return;
  1305. }
  1306. if (ScrollCode == SB_TOP) {
  1307. CurrPage = 1;
  1308. ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, CurrPage );
  1309. ChangeTitle( hwndMain, TiffFileName );
  1310. VscrollPos = 0;
  1311. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1312. PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  1313. return;
  1314. }
  1315. if (ScrollCode == SB_BOTTOM) {
  1316. CurrPage = TiffInfo.PageCount;
  1317. ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, CurrPage );
  1318. ChangeTitle( hwndMain, TiffFileName );
  1319. VscrollPos = 0;
  1320. SetScrollPos( hwnd, SB_VERT, VscrollPos, TRUE );
  1321. PostMessage( hwndView, WM_VIEW_REFRESH, 0, 0 );
  1322. return;
  1323. }
  1324. }
  1325. LRESULT
  1326. ChildWndProc(
  1327. HWND hwnd,
  1328. UINT message,
  1329. WPARAM wParam,
  1330. LPARAM lParam
  1331. )
  1332. {
  1333. static double ZoomPct = 1.00;
  1334. static HDC hdcMem = NULL;
  1335. RECT rc;
  1336. PAINTSTRUCT ps;
  1337. HDC hdc;
  1338. HCURSOR OldCursor;
  1339. int OldScrollPos;
  1340. int Delta;
  1341. HBITMAP hBmp;
  1342. switch (message) {
  1343. case WM_CREATE:
  1344. ZoomPct = Zooms[CurrZoom];
  1345. return 0;
  1346. case WM_VSCROLL:
  1347. ScrollViewVertically( hwnd, LOWORD(wParam), HIWORD(wParam) );
  1348. UpdateScrollInfo( hwnd );
  1349. return 0;
  1350. case WM_HSCROLL:
  1351. OldScrollPos = HscrollPos;
  1352. GetClientRect( hwnd, &rc );
  1353. switch (LOWORD (wParam)) {
  1354. case SB_LINEUP:
  1355. HscrollPos -= HScrollLine;
  1356. break;
  1357. case SB_LINEDOWN:
  1358. HscrollPos += HScrollLine;
  1359. break;
  1360. case SB_PAGEUP:
  1361. HscrollPos -= CxClient;
  1362. break;
  1363. case SB_PAGEDOWN:
  1364. HscrollPos += CxClient;
  1365. break;
  1366. case SB_THUMBPOSITION:
  1367. HscrollPos = HIWORD(wParam);
  1368. break;
  1369. case SB_THUMBTRACK:
  1370. HscrollPos = HIWORD(wParam);
  1371. break;
  1372. }
  1373. HscrollPos = max( 0, min( HscrollPos, (int) HScrollMax ) );
  1374. SetScrollPos( hwnd, SB_HORZ, HscrollPos, TRUE );
  1375. Delta = HscrollPos - OldScrollPos;
  1376. if (Delta != 0) {
  1377. ScrollWindow( hwnd, -Delta, 0, &rc, &rc );
  1378. }
  1379. return 0;
  1380. case WM_PAINT:
  1381. hdc = BeginPaint( hwnd, &ps );
  1382. if (TiffFileOpened) {
  1383. GetClientRect( hwnd, &rc );
  1384. BitBlt(
  1385. hdc,
  1386. ps.rcPaint.left,
  1387. ps.rcPaint.top,
  1388. ps.rcPaint.right - ps.rcPaint.left,
  1389. ps.rcPaint.bottom - ps.rcPaint.top,
  1390. hdcMem,
  1391. HscrollPos + ((int)ps.rcPaint.left - (int)rc.left),
  1392. (VscrollPos%VScrollPage) + ((int)ps.rcPaint.top - (int)rc.top),
  1393. SRCCOPY
  1394. );
  1395. }
  1396. EndPaint( hwnd, &ps );
  1397. return 0;
  1398. case WM_VIEW_CLOSE:
  1399. DeleteDC( hdcMem );
  1400. hdcMem = NULL;
  1401. VscrollPos = 0;
  1402. HscrollPos = 0;
  1403. UpdateScrollInfo( hwnd );
  1404. return 0;
  1405. case WM_VIEW_REFRESH:
  1406. ZoomPct = Zooms[CurrZoom];
  1407. HscrollPos = 0;
  1408. Width = (DWORD)(OrigWidth * ZoomPct);
  1409. Height = (DWORD)(OrigHeight * ZoomPct);
  1410. SetScrollPos( hwnd, SB_HORZ, HscrollPos, TRUE );
  1411. OldCursor = SetCursor( Hourglass );
  1412. DeleteDC( hdcMem );
  1413. hdc = GetDC( hwnd );
  1414. hBmp = CreateCompatibleBitmap( hdc, Width, Height );
  1415. hdcMem = CreateCompatibleDC( hdc );
  1416. SelectObject( hdcMem, hBmp );
  1417. StretchDIBits(
  1418. hdcMem,
  1419. 0,
  1420. 0,
  1421. Width,
  1422. Height,
  1423. 0,
  1424. 0,
  1425. TiffInfo.ImageWidth,
  1426. TiffInfo.ImageHeight,
  1427. TiffData,
  1428. bmi,
  1429. DIB_RGB_COLORS,
  1430. SRCCOPY
  1431. );
  1432. ReleaseDC( hwnd, hdc );
  1433. DeleteObject( hBmp );
  1434. UpdateScrollInfo( hwnd );
  1435. InvalidateRect( hwnd, NULL, TRUE );
  1436. SetCursor( OldCursor );
  1437. return 0;
  1438. case WM_SIZE:
  1439. UpdateScrollInfo( hwnd );
  1440. GetClientRect( hwnd, &rc );
  1441. CyClient = rc.bottom - rc.top;
  1442. CxClient = rc.right - rc.left;
  1443. return 0;
  1444. }
  1445. return DefWindowProc( hwnd, message, wParam, lParam );
  1446. }