home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLSRC.PAK / MEMORYDC.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  5.0 KB  |  229 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1992, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.8  $
  6. //
  7. // Implementation of TMemoryDC and TDibDC encapsulation classes
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #if !defined(OWL_DC_H)
  11. # include <owl/dc.h>
  12. #endif
  13. #if !defined(OWL_GDIOBJEC_H)
  14. # include <owl/gdiobjec.h>
  15. #endif
  16.  
  17. OWL_DIAGINFO;
  18. DIAG_DECLARE_GROUP(OwlGDI);        // General GDI diagnostic group
  19.  
  20. //
  21. // class TMemDCCache
  22. // ~~~~~ ~~~~~~~~~~~
  23. // Cache of screen-compatible memory HDCs used automatically by TMemoryDC when
  24. // the default ctor is called. Reduces the amount of HDC creations & allows
  25. // centralized sharing of these memory HDCs. The cache grows on demand.
  26. //
  27. class TMemDCCache {
  28.   public:
  29.     enum {MaxEntries = 8};          // Max # of mem DCs allowed in the cache
  30.  
  31.     struct TEntry {
  32.       HDC   Handle;
  33.       bool  Busy;
  34.     };
  35.  
  36.     TMemDCCache();
  37.    ~TMemDCCache();
  38.     HDC  Get();
  39.     void Release(HDC hDC);
  40.  
  41.   private:
  42.     TEntry  Entries[MaxEntries];
  43. };
  44.  
  45. //
  46. //
  47. //
  48. TMemDCCache::TMemDCCache()
  49. {
  50.   for (int i = 0; i < MaxEntries; i++) {
  51.     Entries[i].Handle = 0;
  52.     Entries[i].Busy = false;
  53.   }
  54. }
  55.  
  56. //
  57. //
  58. //
  59. TMemDCCache::~TMemDCCache()
  60. {
  61.   for (int i = 0; i < MaxEntries && Entries[i].Handle; i++) {
  62.     WARNX(OwlGDI, Entries[i].Busy, 0, "Unreleased DC " <<
  63.           hex << uint(Entries[i].Handle) << " in MemDCCache at destruction");
  64.     ::DeleteDC(Entries[i].Handle);
  65.   }
  66. }
  67.  
  68. //
  69. // Get a screen compatible memory HDC from the cache, creating one if needed
  70. // and there is room.
  71. //
  72. HDC
  73. TMemDCCache::Get()
  74. {
  75.   for (int i = 0; i < MaxEntries; i++) {
  76.     if (!Entries[i].Handle) {
  77.       // Use a screen dc as reference when constructing the compatible DC
  78.       // since in some rare situations CreateCompatibleDC(0) fails.
  79.       //
  80.       HDC sdc = ::GetWindowDC(0);  
  81.       Entries[i].Handle = ::CreateCompatibleDC(sdc);
  82.       ::ReleaseDC(0, sdc);
  83.     }
  84.     if (!Entries[i].Busy) {
  85.       Entries[i].Busy = true;
  86.       return Entries[i].Handle;
  87.     }
  88.   }
  89.   return 0;  // Cache is full
  90. }
  91.  
  92. //
  93. //
  94. //
  95. void
  96. TMemDCCache::Release(HDC hDC)
  97. {
  98.   for (int i = 0; i < MaxEntries && Entries[i].Handle; i++) {
  99.     if (Entries[i].Handle == hDC) {
  100.       WARNX(OwlGDI, !Entries[i].Busy, 0, "Releasing non-busy DC " <<
  101.             hex << uint(Entries[i].Handle) << " in MemDCCache");
  102.       Entries[i].Busy = false;
  103.       return;
  104.     }
  105.   }
  106. }
  107.  
  108. //
  109. //
  110. //
  111. static TMemDCCache&
  112. GetMemDCCache()
  113. {
  114.   static TMemDCCache MemDCCache;
  115.   return MemDCCache;
  116. }
  117.  
  118. //
  119. // Construct a screen-compatible memory DC. Try to get one from the cache first
  120. //
  121. TMemoryDC::TMemoryDC()
  122. :
  123.   TCreatedDC()
  124. {
  125.   Init();
  126. }
  127.  
  128. //
  129. // Construct a memory DC compatible with a non-screen DC
  130. //
  131. TMemoryDC::TMemoryDC(const TDC& dc)
  132. :
  133.   TCreatedDC()
  134. {
  135.   Handle = ::CreateCompatibleDC(dc);
  136.   CheckValid();
  137.   OrgBitmap = 0;
  138. }
  139.  
  140. //
  141. // Construct a TDC using an existing HDC. Delete it on destruction as
  142. // requested.
  143. //
  144. TMemoryDC::TMemoryDC(HDC handle, TAutoDelete autoDelete)
  145. :
  146.   TCreatedDC(handle, autoDelete)
  147. {
  148. }
  149.  
  150. //
  151. // Construct a screen compatible memory dc & select a bitmap right away
  152. //
  153. TMemoryDC::TMemoryDC(TBitmap& bitmap)
  154. :
  155.   TCreatedDC()
  156. {
  157.   Init();
  158.   SelectObject(bitmap);
  159. }
  160.  
  161. //
  162. // A protected pass-thru constructor for use by derived classes
  163. //
  164. TMemoryDC::TMemoryDC(const char far* driver, const char far* device,
  165.                      const char far* output, const DEVMODE far* initData)
  166. :
  167.   TCreatedDC(driver, device, output, initData)
  168. {
  169. }
  170.  
  171. //
  172. // Initialization for screen compatible DC construction
  173. //
  174. void
  175. TMemoryDC::Init()
  176. {
  177.   Handle = GetMemDCCache().Get();
  178.   if (Handle) {
  179.     ShouldDelete = false;              // Found, let the cache own the handle
  180.   }
  181.   else {
  182.     Handle = ::CreateCompatibleDC(0);  // Cache is full, we own the handle
  183.     CheckValid();
  184.   }
  185.   OrgBitmap = 0;
  186. }
  187.  
  188. //
  189. // Select a bitmap object into this memory DC. This is a new type of object
  190. // selection added on to what TDC can do.
  191. //
  192. void
  193. TMemoryDC::SelectObject(const TBitmap& bitmap)
  194. {
  195.   HBITMAP oldBitmap = (HBITMAP)::SelectObject(HDC(Handle), bitmap);
  196.   if (oldBitmap) {
  197.     TGdiObject::RefInc(bitmap);
  198.     if (uint(oldBitmap) > 1)
  199.       if (!OrgBitmap)
  200.         OrgBitmap = oldBitmap;
  201.       else
  202.         TGdiObject::RefDec(oldBitmap, false);
  203.   }
  204. }
  205.  
  206. //
  207. // Restore the original bitmap object into this memory DC
  208. //
  209. void
  210. TMemoryDC::RestoreBitmap()
  211. {
  212.   if (OrgBitmap) {
  213.     TGdiObject::RefDec(::SelectObject(HDC(Handle), OrgBitmap), false);
  214.     OrgBitmap = 0;
  215.   }
  216. }
  217.  
  218. //
  219. // Destruct this memory DC, restoring all originally selected objects &
  220. // releasing our handle if it may have been from the cache
  221. //
  222. TMemoryDC::~TMemoryDC()
  223. {
  224.   RestoreBitmap();
  225.   RestoreObjects();
  226.   if (!ShouldDelete)  // The HDC is never from the cache if ShouldDelete
  227.     GetMemDCCache().Release(HDC(Handle));
  228. }
  229.