home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / BMPVIEW.PAK / BMPVIEW.CPP next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  21.8 KB  |  872 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1991, 1995 by Borland International, All Rights Reserved
  4. //
  5. //   Example program that shows Dibs, Bitmaps and Palettes in a scrolling
  6. //   Window. Also uses diagnostics to trace thru some routines
  7. //----------------------------------------------------------------------------
  8. #include <owl/pch.h>
  9. #include <owl/applicat.h>
  10. #include <owl/dc.h>
  11. #include <owl/menu.h>
  12. #include <owl/dibitmap.h>
  13. #include <owl/framewin.h>
  14. #include <owl/scroller.h>
  15. #include <owl/opensave.h>
  16. #include <owl/clipview.h>
  17. #include <owl/inputdia.h>
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <dir.h>
  21. #include "bmpview.h"
  22.  
  23. DIAG_DEFINE_GROUP_INIT(OWL_INI, BmpView, 1, 0);
  24.  
  25. #define USE_DDB     // Use a DDB, else blts the DIB directly to the screen
  26. //#define PAINT_ICON  // define to paint the icon from the bitmap
  27.  
  28. static const char AppName[] = "BitmapView";
  29.  
  30. //
  31. // class TWaitCursor
  32. // ~~~~~ ~~~~~~~~~~~
  33. // General wait cursor wrapper. Changes cursor to an hourglass during its scope
  34. //
  35. class TWaitCursor {
  36.   public:
  37.     TWaitCursor()
  38.     :
  39.       HCursor(::SetCursor(::LoadCursor(0, IDC_WAIT)))
  40.     {
  41.     }
  42.  
  43.    ~TWaitCursor()
  44.     {
  45.       ::SetCursor(HCursor);
  46.     }
  47.   private:
  48.     HCURSOR HCursor;
  49. };
  50.  
  51. //
  52. // class TBmpViewWindow
  53. // ~~~~~ ~~~~~~~~~~~~~~
  54. // A bitmap displaying window derived from TClipboardViewer to
  55. // facilitate receiving of clipboard change notifications. Could mix it in if
  56. // an additional base was desired.
  57. //
  58. class _USERCLASS TBmpViewWindow : virtual public TWindow,
  59.                                           public TClipboardViewer {
  60.   public:
  61.     bool      ScreenPalettized;  // True if the screen is a palettized device
  62.     TPalette* DefPalette;        // Palette to use for DIBs w/o color tables
  63.     TBrush*   BkgndBrush;        // Window background brush
  64.     long      Rop;               // Bitmap -> screen raster op
  65.  
  66.     bool      Fit;               // Stretch bitmap to fit?
  67.     bool      AutoClipView;      // Clipboard auto-display mode
  68.     bool      PaintFromDDB;      // Paint DDB to screen, vs. DIB
  69.     bool      PaintIcon;         // Paint icon from DIB, vs. from resource
  70.  
  71.     string    FileName;
  72.     TDib*     Dib;
  73.     TBitmap*  Bitmap;
  74.     HBITMAP   MemHandle;
  75.     TPalette* Palette;
  76.     int       PixelWidth;
  77.     int       PixelHeight;
  78.     uint16    Colors;
  79.  
  80.     TBmpViewWindow();
  81.    ~TBmpViewWindow();
  82.  
  83.   protected:
  84.     void      CmFileOpen();
  85.     void      CmRead1();
  86.     void      CmRead2();
  87.     void      CmReadBad();
  88.     void      CmMemHandle();
  89.     void      CmMemHandleRefresh();
  90.     void      CmCopy();
  91.     void      CmPaste();
  92.     void      CmFit();
  93.     void      CmAutoClipView();
  94.     void      CmPaintFromDDB();
  95.     void      CmPaintIcon();
  96.     void      CeCopy(TCommandEnabler& ce);
  97.     void      CePaste(TCommandEnabler& ce);
  98.     void      CeFit(TCommandEnabler& ce);
  99.     void      CeAutoClipView(TCommandEnabler& ce);
  100.     void      CePaintFromDDB(TCommandEnabler& ce);
  101.     void      CePaintIcon(TCommandEnabler& ce);
  102.  
  103.     void      Paint(TDC&, bool erase, TRect&);
  104.     void      EvSize(uint sizeType, TSize&);
  105.  
  106.     void      EvPaletteChanged(HWND hWndPalChg);
  107.     bool      EvQueryNewPalette();
  108.     void      EvDrawClipboard();
  109.     void      EvDestroy();
  110.  
  111.     bool      UpdatePalette(bool alwaysRepaint);
  112.     void      AdjustScroller();
  113.     void      SetCaption(const char*);
  114.     void      SetupFromDib(TDib* dib);
  115.     bool      LoadBitmapFile(const char*);
  116.     bool      LoadBitmapResource(uint16 resId);
  117.     bool      LoadMemHandle(HBITMAP hBitmap);
  118.  
  119.   DECLARE_RESPONSE_TABLE(TBmpViewWindow);
  120. };
  121.  
  122. DEFINE_RESPONSE_TABLE2(TBmpViewWindow, TClipboardViewer, TWindow)
  123.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  124.   EV_COMMAND(CM_READ1, CmRead1),
  125.   EV_COMMAND(CM_READ2, CmRead2),
  126.   EV_COMMAND(CM_READBAD, CmReadBad),
  127.   EV_COMMAND(CM_MEMHANDLE, CmMemHandle),
  128.   EV_COMMAND(CM_MEMHANDLEREFRESH, CmMemHandleRefresh),
  129.   EV_COMMAND(CM_EDITCOPY, CmCopy),
  130.   EV_COMMAND(CM_EDITPASTE, CmPaste),
  131.   EV_COMMAND(CM_FIT, CmFit),
  132.   EV_COMMAND(CM_AUTOCLIPVIEW, CmAutoClipView),
  133.   EV_COMMAND(CM_PAINTFROMDDB, CmPaintFromDDB),
  134.   EV_COMMAND(CM_PAINTICON, CmPaintIcon),
  135.   EV_COMMAND_ENABLE(CM_EDITCOPY, CeCopy),
  136.   EV_COMMAND_ENABLE(CM_EDITPASTE, CePaste),
  137.   EV_COMMAND_ENABLE(CM_FIT, CeFit),
  138.   EV_COMMAND_ENABLE(CM_AUTOCLIPVIEW, CeAutoClipView),
  139.   EV_COMMAND_ENABLE(CM_PAINTFROMDDB, CePaintFromDDB),
  140.   EV_COMMAND_ENABLE(CM_PAINTICON, CePaintIcon),
  141.   EV_WM_SIZE,
  142.   EV_WM_PALETTECHANGED,
  143.   EV_WM_QUERYNEWPALETTE,
  144.   EV_WM_DRAWCLIPBOARD,
  145.   EV_WM_DESTROY,
  146. END_RESPONSE_TABLE;
  147.  
  148. //
  149. // Constructor for a TBmpViewWindow, sets scroll styles and constructs
  150. // the Scroller object.  Also sets the Rop based on whether the display
  151. // is monochrome (two-color) or polychrome.
  152. //
  153. TBmpViewWindow::TBmpViewWindow()
  154. :
  155.   TWindow(0, 0, 0),
  156.   TClipboardViewer()
  157. {
  158.  
  159.   Attr.Style |= WS_BORDER | WS_VSCROLL | WS_HSCROLL;
  160.   Attr.ExStyle |= WS_EX_CLIENTEDGE;
  161.  
  162.   BkgndBrush = new TBrush(TColor::SysWindow);
  163.   Scroller = new TScroller(this, 1, 1, 200, 200);
  164.  
  165.   Fit = false;
  166.   AutoClipView = false;
  167.   PaintFromDDB = true;
  168.   PaintIcon = false;
  169.  
  170.   Dib = 0;
  171.   Bitmap = 0;
  172.   MemHandle = 0;
  173.   Palette = 0;
  174.  
  175.   // If the screen is a palettized device, then we'll need a halftone palette
  176.   // for dibs with > 8 bpp
  177.   //
  178.   TScreenDC screenDC;
  179.   if (screenDC.GetDeviceCaps(RASTERCAPS) & RC_PALETTE) {
  180.     ScreenPalettized = true;
  181. #if defined(BI_PLAT_WIN32)
  182.     DefPalette = new THalftonePalette;
  183. #else
  184.     DefPalette = new TPalette((HPALETTE)::GetStockObject(DEFAULT_PALETTE));
  185. #endif
  186.   }
  187.   else {
  188.     ScreenPalettized = false;
  189.     DefPalette = 0;
  190.   }
  191.  
  192.   // Raster op to use when blitting to the screen
  193.   //
  194.   Rop = SRCCOPY;
  195.  
  196.   SetCaption(0);
  197.   SetBkgndColor(TColor::Transparent);  // Don't pre-erase image background
  198. }
  199.  
  200. //
  201. //
  202. //
  203. TBmpViewWindow::~TBmpViewWindow()
  204. {
  205.   delete Bitmap;
  206.   if (Palette != DefPalette)
  207.     delete Palette;
  208.   delete DefPalette;
  209.   delete Dib;
  210.   delete BkgndBrush;
  211. }
  212.  
  213. //
  214. // Build up a caption based on a filename, and set it into the title.
  215. //
  216. void
  217. TBmpViewWindow::SetCaption(const char* name)
  218. {
  219.   FileName = name ? name : "untitled";
  220.  
  221.   if (Parent) {
  222. #if 0 // Old title format
  223.     string caption = string(GetApplication()->GetName()) + " - " + FileName;
  224. #else
  225.     string caption = FileName + " - " + GetApplication()->GetName();
  226. #endif
  227.     Parent->SetCaption(caption.c_str());
  228.   }
  229. }
  230.  
  231. //
  232. // Make a metafile & put it on the clipboard.
  233. // Make a copy of each of the objects & place the copies on the clipboard
  234. //
  235. void
  236. TBmpViewWindow::CmCopy()
  237. {
  238.   TClipboard clipboard(*this);
  239.  
  240.   if (clipboard.EmptyClipboard()) {
  241.     TMetaFileDC mfDC;
  242.     mfDC.SetWindowExt(Dib->Size());
  243.     mfDC.SetWindowOrg(0, 0);
  244.     mfDC.SetDIBitsToDevice(TRect(0,0, PixelWidth, PixelHeight), TPoint(0,0), *Dib);
  245.     TMetaFilePict mf(mfDC.Close(), AutoDelete);
  246.     mf.ToClipboard(clipboard, MM_TEXT, TSize(PixelWidth, PixelHeight));
  247.  
  248.     if (Palette)
  249.       TPalette(*Palette).ToClipboard(clipboard);
  250.     TDib(*Dib).ToClipboard(clipboard);
  251.     if (Bitmap)
  252.       TBitmap(*Bitmap).ToClipboard(clipboard);
  253.   }
  254. }
  255.  
  256. void
  257. TBmpViewWindow::CeCopy(TCommandEnabler& ce)
  258. {
  259.   ce.Enable(Dib != 0);
  260. }
  261.  
  262. //
  263. // When a user selects edit.paste, get the data from the clipboard. This
  264. // routine prefers CF_META over CF_DIB over CF_BITMAP
  265. //
  266. void
  267. TBmpViewWindow::CmPaste()
  268. {
  269.   TClipboard clipboard(*this);
  270.   if (!clipboard)
  271.     return;
  272.  
  273.   TPalette* newPal = 0;
  274.   TDib*     newDib = 0;
  275.   TBitmap*  newBitmap;
  276.  
  277.   // If there is a palette on the clipboard, get it & realize it
  278.   //
  279.   if (clipboard.IsClipboardFormatAvailable(CF_PALETTE)) {
  280.     newPal = new TPalette(TPalette(clipboard));  // make a copy
  281.     UpdatePalette(false);
  282.   }
  283.  
  284.   // try DIB format 1st
  285.   //
  286.   if (clipboard.IsClipboardFormatAvailable(CF_DIB)) {
  287.     newDib = new TDib(TDib(clipboard));        // make a copy
  288.     newBitmap = new TBitmap(*newDib, newPal);  // newPal==0 is OK
  289.   }
  290.   // try metafile 2nd
  291.   //
  292.   else if (clipboard.IsClipboardFormatAvailable(CF_METAFILEPICT)) {
  293.     if (!newPal)
  294.       newPal = new TPalette((HPALETTE)GetStockObject(DEFAULT_PALETTE));
  295.     newBitmap = new TBitmap(TMetaFilePict(clipboard), *newPal,
  296.                             GetClientRect().Size());
  297.   }
  298.   // try bitmap (DDB) format 3rd
  299.   //
  300.   else if (clipboard.IsClipboardFormatAvailable(CF_BITMAP)) {
  301.     newBitmap = new TBitmap(TBitmap(clipboard));     // make a copy
  302.   }
  303.   else
  304.     return;  // Should never happen--this command is enabled by above tests
  305.  
  306.   // Got a bitmap & maybe more. Now keep it & setup things.
  307.   //
  308.   delete Bitmap;
  309.   Bitmap = newBitmap;
  310.  
  311.   // Make a DIB from the bitmap if we didn't get one yet.
  312.   //
  313.   if (!newDib)
  314.     newDib = new TDib(*newBitmap, newPal);
  315.   delete Dib;
  316.   Dib = newDib;
  317.  
  318.   // Either use the palette obtained above, or construct one from the
  319.   // color table in the DIB
  320.   //
  321.   try {
  322.     if (!newPal)
  323.       newPal = new TPalette(*newDib);
  324.   }
  325.   catch (...) {
  326. #if defined(BI_PLAT_WIN32)
  327.     newPal = new TPalette(::CreateHalftonePalette(TScreenDC()), AutoDelete);
  328. #else
  329.     throw TXOwl("Cannot create palette from DIB");
  330. #endif
  331. //    newPal = new TPalette((HPALETTE)::GetStockObject(DEFAULT_PALETTE));
  332.   }
  333.   if (Palette != DefPalette)
  334.     delete Palette;
  335.   Palette = newPal;
  336.   Palette->GetObject(Colors);
  337.  
  338.   PixelWidth  = Dib->Width();
  339.   PixelHeight = Dib->Height();
  340.   AdjustScroller();
  341.   SetCaption("clipboard");
  342.  
  343.   // We'll paint the icon from the bitmap, or use the icon in the resource
  344.   //
  345.   if (PaintIcon)
  346.     GetApplication()->GetMainWindow()->SetIcon(0, 0);
  347.   else
  348.     GetApplication()->GetMainWindow()->SetIcon(GetApplication(), GetApplication()->GetName());
  349. }
  350.  
  351. //
  352. //
  353. //
  354. void
  355. TBmpViewWindow::CePaste(TCommandEnabler& ce)
  356. {
  357.   TClipboard clipboard(*this);
  358.   ce.Enable(
  359.     clipboard && (
  360.       clipboard.IsClipboardFormatAvailable(CF_METAFILEPICT) ||
  361.       clipboard.IsClipboardFormatAvailable(CF_DIB) ||
  362.       clipboard.IsClipboardFormatAvailable(CF_BITMAP)
  363.     )
  364.   );
  365. }
  366.  
  367. //
  368. // If either of the "Read bitmap" menu items is selected, then we read
  369. // the bitmap resource with the ID of the menu item...
  370. //
  371. void
  372. TBmpViewWindow::CmRead1()
  373. {
  374.   if (LoadBitmapResource(CM_READ1))
  375.     SetCaption("(Bitmap resource 1)");
  376. }
  377.  
  378. //
  379. //
  380. //
  381. void
  382. TBmpViewWindow::CmRead2()
  383. {
  384.   if (LoadBitmapResource(CM_READ2))
  385.     SetCaption("(Bitmap resource 2)");
  386. }
  387.  
  388. void
  389. TBmpViewWindow::CmReadBad()
  390. {
  391.   LoadBitmapFile("");   // force a failure for kicks
  392. }
  393.  
  394. //
  395. //
  396. //
  397. void
  398. TBmpViewWindow::CmMemHandle()
  399. {
  400.   char buf[32];
  401.   sprintf(buf, "%0X", MemHandle);
  402.   if (TInputDialog(this, "Memory Bitmap", "Enter handle", buf, sizeof buf).Execute() == IDOK) {
  403.     HBITMAP handle;
  404.     sscanf(buf, "%x", &handle);
  405.     LoadMemHandle(handle);
  406.   }
  407. }
  408.  
  409. //
  410. // Reload the bitmaps from the user supplied bitmap handle
  411. //
  412. void
  413. TBmpViewWindow::CmMemHandleRefresh()
  414. {
  415.   if (MemHandle)
  416.     LoadMemHandle(MemHandle);
  417. }
  418.  
  419. //
  420. // Toggle Fit member variable & adjust scroller as needed
  421. //
  422. void
  423. TBmpViewWindow::CmFit()
  424. {
  425.   Fit = !Fit;
  426.   AdjustScroller();
  427. }
  428.  
  429. //
  430. // The fit menu item is checked if the Fit member is true
  431. //
  432. void
  433. TBmpViewWindow::CeFit(TCommandEnabler& ce)
  434. {
  435.   ce.SetCheck(Fit ? TCommandEnabler::Checked : TCommandEnabler::Unchecked);
  436. }
  437.  
  438. //
  439. // Toggle AutoAutoClipView member variable
  440. //
  441. void
  442. TBmpViewWindow::CmAutoClipView()
  443. {
  444.   AutoClipView = !AutoClipView;
  445. }
  446.  
  447. //
  448. // Check AutoClipView according to flag
  449. //
  450. void
  451. TBmpViewWindow::CeAutoClipView(TCommandEnabler& ce)
  452. {
  453.   ce.SetCheck(AutoClipView ? TCommandEnabler::Checked : TCommandEnabler::Unchecked);
  454. }
  455.  
  456. //
  457. // Toggle PaintFromDDB member variable
  458. //
  459. void
  460. TBmpViewWindow::CmPaintFromDDB()
  461. {
  462.   PaintFromDDB = !PaintFromDDB;
  463.   Invalidate();
  464. }
  465.  
  466. //
  467. // Check AutoClipView according to flag
  468. //
  469. void
  470. TBmpViewWindow::CePaintFromDDB(TCommandEnabler& ce)
  471. {
  472.   ce.SetCheck(PaintFromDDB ? TCommandEnabler::Checked : TCommandEnabler::Unchecked);
  473. }
  474.  
  475. //
  476. // Toggle PaintIcon member variable
  477. //
  478. void
  479. TBmpViewWindow::CmPaintIcon()
  480. {
  481.   PaintIcon = !PaintIcon;
  482. }
  483.  
  484. //
  485. // Check AutoClipView according to flag
  486. //
  487. void
  488. TBmpViewWindow::CePaintIcon(TCommandEnabler& ce)
  489. {
  490.   ce.SetCheck(PaintIcon ? TCommandEnabler::Checked : TCommandEnabler::Unchecked);
  491. }
  492.  
  493. //
  494. // If the the "Open..." menu item is selected, then we prompt the user
  495. // for a new bitmap file.  If the user selects one and it is one that
  496. // we can read, we display it in the window and change the window's
  497. // caption to reflect the new bitmap file.
  498. //
  499. void
  500. TBmpViewWindow::CmFileOpen()
  501. {
  502.   static TOpenSaveDialog::TData data (
  503.     OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOREADONLYRETURN,
  504.     "Bitmap Files (*.BMP)|*.bmp|",
  505.     0,
  506.     "",
  507.     "BMP"
  508.   );
  509.   if (TFileOpenDialog(this, data).Execute() == IDOK) {
  510.     char fileTitle[MAXPATH];
  511.     TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
  512.     LoadBitmapFile(fileTitle);
  513.     SetCaption(strlwr(fileTitle));
  514.   }
  515. }
  516.  
  517. //
  518. // Adjust the Scroller range so that the the origin is the
  519. // upper-most scrollable point and the corner is the
  520. // bottom-most.
  521. //
  522. void
  523. TBmpViewWindow::AdjustScroller()
  524. {
  525.   TRect  clientRect = GetClientRect();
  526.  
  527.   // Only show scrollbars when image is larger than
  528.   // the client area and we are not stretching to fit.
  529.   //
  530.   if (Fit) {
  531.     Scroller->SetRange(0, 0);
  532.   }
  533.   else {
  534.     TPoint Range(Max(PixelWidth-clientRect.Width(), 0),
  535.                  Max(PixelHeight-clientRect.Height(), 0));
  536.     Scroller->SetRange(Range.x, Range.y);
  537.   }
  538.   Scroller->ScrollTo(0, 0);
  539.   if (!GetUpdateRect(clientRect, false))
  540.     Invalidate(false);
  541. }
  542.  
  543. //
  544. // Reset scroller range.
  545. //
  546. void
  547. TBmpViewWindow::EvSize(uint SizeType, TSize& Size)
  548. {
  549.   TWindow::EvSize(SizeType, Size);
  550.   if (SizeType != SIZEICONIC) {
  551.     AdjustScroller();
  552.     Invalidate(false);
  553.   }
  554. }
  555.  
  556. //
  557. // Somebody changed the palette. If its not us, then we need to update.
  558. //
  559. void
  560. TBmpViewWindow::EvPaletteChanged(HWND hWndPalChg)
  561. {
  562.   if (hWndPalChg != GetHandle())
  563.     UpdatePalette(false);    // pass false to UpdateColors() instead of repaint
  564. }
  565.  
  566. //
  567. // We need to re-realize the logical palette each time we regain the input
  568. // focus
  569. //
  570. bool
  571. TBmpViewWindow::EvQueryNewPalette()
  572. {
  573.   return UpdatePalette(true);
  574. }
  575.  
  576. //
  577. //
  578. //
  579. void
  580. TBmpViewWindow::EvDrawClipboard()
  581. {
  582.   if (TClipboardViewer::DoDrawClipboard() == esComplete)
  583.     return;
  584.   if (AutoClipView)
  585.     CmPaste();
  586. }
  587.  
  588. //
  589. //
  590. //
  591. void
  592. TBmpViewWindow::EvDestroy()
  593. {
  594.   if (TClipboardViewer::DoDestroy() == esComplete)
  595.     return;
  596.   TWindow::EvDestroy();
  597. }
  598.  
  599. //
  600. //
  601. //
  602. bool
  603. TBmpViewWindow::UpdatePalette(bool alwaysRepaint)
  604. {
  605.   TRACEX(BmpView, 2, "Enter UpdatePalette()");
  606.   if (ScreenPalettized && Palette) {
  607.     TClientDC clientDC(*this);
  608. #if defined(BI_PLAT_WIN16)
  609.     Palette->UnrealizeObject();
  610. #endif
  611.     TRACEX(BmpView, 2, "UpdatePalette::Palette: " << hex << (uint)(HPALETTE)*Palette);
  612.     clientDC.SelectObject(*Palette, true); 
  613.     bool needsUpdate = clientDC.RealizePalette() > 0;
  614.     if (alwaysRepaint || needsUpdate)
  615.       Invalidate(false);
  616. //    else if (needsUpdate)
  617. //      clientDC.UpdateColors(); // can use this, but our painting is faster
  618.     TRACEX(BmpView, 2, "Leave UpdatePalette(true)");
  619.     return true;
  620.   }
  621.   TRACEX(BmpView, 2, "Leave UpdatePalette(false)");
  622.   return false;
  623. }
  624.  
  625. //
  626. // Responds to an incoming Paint message by redrawing the bitmap.
  627. // The Scroller's BeginView method, which sets the viewport origin
  628. // relative to the present scroll position, has been called by TWindow's
  629. // EvPaint
  630. // Note that we Invalidate() ourselves with false to avoid the background
  631. // paint flicker. Thats why we use
  632. //
  633. // The code can use either the Bitmap member with Stretch- and Bit- Blts,
  634. // or use the Dib member with Stretch- and Set- DIBits...
  635. //
  636. void
  637. TBmpViewWindow::Paint(TDC& dc, bool, TRect&)
  638. {
  639.   TRACEX(BmpView, 2, "Enter Paint()");
  640.   TRect clientRect = GetClientRect();
  641.  
  642.   TRACEX(BmpView, 2, "Paint::BkBrush: " << hex << (uint)(HBRUSH)*BkgndBrush);
  643.   dc.SelectObject(*BkgndBrush);
  644.  
  645.   TMemoryDC memoryDC(dc);  // Get ready to possibly use the DDB
  646.  
  647.   if (PaintFromDDB && Bitmap) {
  648.     TRACEX(BmpView, 2, "Paint::Bitmap: " << hex << (uint)(HBITMAP)*Bitmap);
  649.     memoryDC.SelectObject(*Bitmap);
  650. //    dc.SetStretchBltMode(STRETCH_HALFTONE);
  651.     dc.SetStretchBltMode(STRETCH_ORSCANS);
  652.     if (Palette) {
  653.       TRACEX(BmpView, 2, "Paint::Palette: " << hex << (uint)(HPALETTE)*Palette);
  654.       dc.SelectObject(*Palette, false);
  655.       dc.RealizePalette();
  656.       memoryDC.SelectObject(*Palette, false);
  657.       memoryDC.RealizePalette();  
  658.     }
  659.     if (Rop == SRCCOPY) {
  660.       if (Colors == 2) {
  661.         if (Palette) {
  662.           PALETTEENTRY pe;
  663.           Palette->GetPaletteEntry(0, pe);
  664.           dc.SetTextColor(TColor(pe));
  665.           Palette->GetPaletteEntry(1, pe);
  666.           dc.SetBkColor(TColor(pe));
  667.         }
  668.         else {
  669.           dc.SetBkColor(TColor(0,0,0));
  670.           dc.SetTextColor(TColor(255,255,255));
  671.         }
  672.       }
  673.     }
  674.   }
  675.  
  676.   if (PaintFromDDB && Bitmap || !PaintFromDDB && Dib) {
  677.     TRect imageRect(0,0, PixelWidth, PixelHeight);
  678.     if (Parent->IsIconic()) {
  679.       if (PaintFromDDB)
  680.         dc.StretchBlt(Parent->GetClientRect(), memoryDC, imageRect, Rop);
  681.       else
  682.         dc.StretchDIBits(Parent->GetClientRect(), imageRect, *Dib, Rop);
  683.     }
  684.     else {
  685.       clientRect += TPoint((int)Scroller->XPos, (int)Scroller->YPos);
  686.       if (Fit) {
  687.         // Stretch to fit
  688.         //
  689.         if (PaintFromDDB)
  690.           dc.StretchBlt(clientRect, memoryDC, imageRect, Rop);
  691.         else
  692.           dc.StretchDIBits(clientRect, imageRect, *Dib);
  693.       }
  694.       else {
  695.         // Let it clip
  696.         //
  697.         if (PaintFromDDB)
  698.           dc.BitBlt(imageRect, memoryDC, TPoint(0,0), Rop);
  699.         else
  700.           dc.SetDIBitsToDevice(imageRect, TPoint(0,0), *Dib);
  701.  
  702.         // Clear borders here for no flicker
  703.         //
  704.         dc.PatBlt(TRect(TPoint(PixelWidth,0), clientRect.BottomRight()));
  705.         dc.PatBlt(TRect(TPoint(0,PixelHeight), clientRect.BottomRight()));
  706.       }
  707.     }
  708.   }
  709.   else
  710.     // Nothing to paint
  711.     //
  712.     dc.PatBlt(clientRect, PATCOPY);
  713.  
  714.   TRACEX(BmpView, 2, "Leave Paint()" << endl);
  715. }
  716.  
  717. //
  718. // Setup all of the bitmap related members given a new dib
  719. //
  720. void
  721. TBmpViewWindow::SetupFromDib(TDib* dib)
  722. {
  723.   TRACEX(BmpView, 1, "Enter SetupFromDib()");
  724.   TRACEX(BmpView, 1, "SetupFromDib::Dib: " << hex << (uint)(HANDLE)*dib);
  725.  
  726.   delete Dib;
  727.   Dib = dib;
  728.  
  729.   if (Palette != DefPalette)
  730.     delete Palette;
  731.   Palette = 0;
  732.   try {
  733.     Palette = new TPalette(*dib);
  734.   }
  735.   catch (...) {
  736. //    Palette = new TPalette(::CreateHalftonePalette(TScreenDC()), AutoDelete);
  737.     Palette = DefPalette;
  738.   }
  739.  
  740.   TRACEX(BmpView, 1, "SetupFromDib::Palette: " << hex << (uint)(HPALETTE)*Palette);
  741.  
  742.   {
  743.     TWaitCursor w;
  744.     delete Bitmap;
  745.     Bitmap = new TBitmap(*Dib, Palette);
  746.     TRACEX(BmpView, 1, "SetupFromDib::Bitmap: " << hex << (uint)(HBITMAP)*Bitmap);
  747.   }
  748.  
  749.   PixelWidth  = Dib->Width();
  750.   PixelHeight = Dib->Height();
  751.  
  752.   UpdatePalette(true);
  753.   AdjustScroller();
  754.  
  755.   // We'll paint the icon from the bitmap, or use the icon in the resource
  756.   //
  757.   if (PaintIcon)
  758.     GetApplication()->GetMainWindow()->SetIcon(0, 0);
  759.   else
  760.     GetApplication()->GetMainWindow()->SetIcon(GetApplication(), GetApplication()->GetName());
  761.  
  762.   TRACEX(BmpView, 1, "Leave SetupFromDib()");
  763. }
  764.  
  765. //
  766. // Test if the passed resource is a Windows 3.0 (or PM 1.x) DI bitmap
  767. // and if so read it.
  768. // Report errors if unable to do so. Adjust the Scroller to the new
  769. // bitmap dimensions.
  770. //
  771. bool
  772. TBmpViewWindow::LoadBitmapResource(uint16 resId)
  773. {
  774.   TDib* newDib;
  775.   try {
  776.     newDib = new TDib(*GetModule(), TResId(resId));
  777.   }
  778.   catch (TXGdi) {
  779.     MessageBox("Cannot access bitmap resource", GetApplication()->GetName(),
  780.                MB_OK);
  781.     return false;
  782.   }
  783.   SetupFromDib(newDib);
  784.   return true;
  785. }
  786.  
  787. //
  788. // Test if the passed file is a Windows 3.0 DI (or PM 1.x) bitmap
  789. // and if so read it.
  790. // Report errors if unable to do so. Adjust the Scroller to the new
  791. // bitmap dimensions.
  792. //
  793. bool
  794. TBmpViewWindow::LoadBitmapFile(const char* name)
  795. {
  796.   TDib* newDib;
  797.   try {
  798.     newDib = new TDib(name);
  799.   }
  800.   catch (TXGdi) {
  801.     MessageBox("Cannot open bitmap file", GetApplication()->GetName(), MB_OK);
  802.     return false;
  803.   }
  804.   SetupFromDib(newDib);
  805.   return true;
  806. }
  807.  
  808. //
  809. //
  810. //
  811. bool
  812. TBmpViewWindow::LoadMemHandle(HBITMAP handle)
  813. {
  814. #if defined(USE_DDB)
  815. #if defined(BI_PLAT_WIN32)
  816.   // Reqest size of info. buffer to validate HBITMAP 
  817.   //
  818.   if (::GetObject(handle, 0, 0)) {
  819. #else
  820.   if (::IsGDIObject(handle)) {
  821. #endif
  822.     TDib* newDib;
  823.     try {
  824.       newDib = new TDib(TBitmap(handle));
  825.       SetupFromDib(newDib);
  826.       MemHandle = handle;
  827.  
  828.       char buf[20];
  829.       sprintf(buf, "hbm:%0X", MemHandle);
  830.       SetCaption(buf);
  831.       return true;
  832.     }
  833.     catch (TXGdi) {
  834.       MessageBox("Cannot construct Dib from HBITMAP",
  835.                  GetApplication()->GetName(), MB_OK);
  836.     }
  837.   }
  838.   else
  839.     MessageBox("Not a valid bitmap handle",
  840.                 GetApplication()->GetName(), MB_OK);
  841. #endif
  842.   return false;
  843. }
  844.  
  845. //----------------------------------------------------------------------------
  846.  
  847. //
  848. // class TBmpViewApp
  849. // ~~~~~ ~~~~~~~~~~~
  850. class _USERCLASS TBmpViewApp : public TApplication {
  851.   public:
  852.     TBmpViewApp(const char far* name) : TApplication(name) {}
  853.     void InitMainWindow() {
  854.       TFrameWindow* frame = new TFrameWindow(0, Name, new TBmpViewWindow);
  855.       frame->AssignMenu(Name);
  856.       frame->SetIcon(this, Name);
  857.       frame->Attr.AccelTable = IDA_BMPVIEW;
  858.       SetMainWindow(frame);
  859.     }
  860. };
  861.  
  862. //----------------------------------------------------------------------------
  863.  
  864. //
  865. //
  866. //
  867. int
  868. OwlMain(int /*argc*/, char* /*argv*/ [])
  869. {
  870.   return TBmpViewApp(AppName).Run();
  871. }
  872.