home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / OLEDLG.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  26.8 KB  |  1,128 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
  4. //
  5.  //   Defines type TOleDialog, the base class of all OLE Dialog classes
  6. //----------------------------------------------------------------------------
  7. #define INC_OLE2
  8. #include <owl/owlpch.h>
  9. #include <owl/dialog.h>
  10. #include <owl/opensave.h>
  11. #include <owl/listbox.h>
  12. #include <owl/radiobut.h>
  13. #include <owl/checkbox.h>
  14. #include <owl/groupbox.h>
  15. #include <owl/edit.h>
  16. #include <ocf/ocview.h>
  17. #include <dir.h>
  18. #include <owl/oledlg.h>
  19.  
  20. //
  21. // Owl OLE Dialog general diagnostic group
  22. //
  23. DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlOleDlg, 1, 0);
  24.  
  25. //
  26. // Helper variables
  27. //
  28. extern const char ClsIdStr[] = "\\CLSID";
  29. const  char PrefixFmt[] = "%c%c%c...\\";
  30.  
  31. //
  32. // Returns OBJECTDESCRIPTOR handle
  33. //
  34. HGLOBAL
  35. TOleDialog::GetObjectDescriptorData(CLSID clsid, DWORD dwDrawAspect,
  36.                                     SIZEL sizel, POINTL pointl,
  37.                                     DWORD dwStatus,
  38.                                     LPSTR lpszFullUserTypeName,
  39.                                     LPSTR lpszSrcOfCopy)
  40. {
  41.   //
  42.   // Length of full user name
  43.   //
  44.   DWORD dwFullUserTypeNameLen = lpszFullUserTypeName ?
  45.                   strlen(lpszFullUserTypeName)+1 : 0;
  46.  
  47.   //
  48.   // Length of source copy string
  49.   //
  50.   DWORD dwSrcOfCopyLen;
  51.   if (lpszSrcOfCopy)
  52.     dwSrcOfCopyLen = strlen(lpszSrcOfCopy)+1;
  53.   else {
  54.     //
  55.     // User user type name as source string
  56.     //
  57.     lpszSrcOfCopy =  lpszFullUserTypeName;
  58.     dwSrcOfCopyLen = dwFullUserTypeNameLen;
  59.   }
  60.  
  61.   //
  62.   // Allocate space for OBJECTDESCRIPTOR and the additional string data
  63.   //
  64.   DWORD dwObjectDescSize = sizeof(OBJECTDESCRIPTOR);
  65.   HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
  66.                              dwObjectDescSize + dwFullUserTypeNameLen +
  67.                              dwSrcOfCopyLen);
  68.  
  69.   //
  70.   // Bail out of memory failure
  71.   //
  72.   if (!hMem)
  73.     return 0;
  74.  
  75.   LPOBJECTDESCRIPTOR lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
  76.  
  77.   //
  78.   // Set the FullUserTypeName offset and copy the string
  79.   //
  80.   if (lpszFullUserTypeName) {
  81.     lpOD->dwFullUserTypeName = dwObjectDescSize;
  82.     strcpy((LPSTR)lpOD + (int)lpOD->dwFullUserTypeName, lpszFullUserTypeName);
  83.   }
  84.   else {
  85.      //
  86.      // zero offset indicates that string is not present
  87.      //
  88.     lpOD->dwFullUserTypeName = 0;
  89.   }
  90.  
  91.   //
  92.   // Set the SrcOfCopy offset and copy the string
  93.   //
  94.   if (lpszSrcOfCopy) {
  95.     lpOD->dwSrcOfCopy = dwObjectDescSize + dwFullUserTypeNameLen;
  96.     strcpy((LPSTR)lpOD+(int)lpOD->dwSrcOfCopy , lpszSrcOfCopy);
  97.   }
  98.   else {
  99.     //
  100.     // zero offset indicates that string is not present
  101.     //
  102.     lpOD->dwSrcOfCopy = 0;
  103.   }
  104.  
  105.   //
  106.   // Initialize the rest of the OBJECTDESCRIPTOR
  107.   //
  108.   lpOD->cbSize       = dwObjectDescSize + dwFullUserTypeNameLen +
  109.                        dwSrcOfCopyLen;
  110.   lpOD->clsid        = clsid;
  111.   lpOD->dwDrawAspect = dwDrawAspect;
  112.   lpOD->sizel        = sizel;
  113.   lpOD->pointl       = pointl;
  114.   lpOD->dwStatus     = dwStatus;
  115.  
  116.   GlobalUnlock(hMem);
  117.   return hMem;
  118. }
  119.  
  120. //
  121. // Retrieve data from an IDataObject in a specified format on a
  122. // global memory block. This function ALWAYS returns a private copy
  123. // of the data to the caller. if necessary a copy is made of the
  124. // data (ie. if lpMedium->pUnkForRelease != 0). The caller assumes
  125. // ownership of the data block in all cases and must free the data
  126. // when done with it. The caller may directly free the data handle
  127. // returned (taking care whether it is a simple HGLOBAL or a HANDLE
  128. // to a MetafilePict) or the caller may call
  129. // ReleaseStgMedium(lpMedium). this OLE helper function will do the
  130. // right thing.
  131. //
  132. HGLOBAL
  133. TOleDialog::GetData(LPDATAOBJECT lpDataObj, CLIPFORMAT cfFormat,
  134.                     DVTARGETDEVICE FAR* lpTargetDevice,
  135.                     DWORD dwDrawAspect, LPSTGMEDIUM lpMedium)
  136. {
  137.   FORMATETC formatetc;
  138.  
  139.   // Init FORMATETC structure
  140.   //
  141.   DWORD tymed;
  142.   switch (cfFormat) {
  143.     case CF_METAFILEPICT:
  144.       tymed = TYMED_MFPICT;
  145.       break;
  146.  
  147.     case CF_BITMAP:
  148.       tymed = TYMED_GDI;
  149.       break;
  150.  
  151.     default:
  152.       tymed = TYMED_HGLOBAL;
  153.       break;
  154.   }
  155.   InitFormatEtc(formatetc, cfFormat, tymed, -1, dwDrawAspect, lpTargetDevice);
  156.  
  157.   TRACEX(OwlOleDlg, 1, "IDataObject::GetData called");
  158.   if (lpDataObj->GetData((LPFORMATETC)&formatetc, lpMedium) != NOERROR)
  159.     return 0;
  160.  
  161.   HGLOBAL hGlobal = lpMedium->hGlobal;  //!CQ nonamelessunion? u.
  162.   if (!hGlobal)
  163.     return 0;
  164.  
  165.   //
  166.   // Check if hGlobal really points to valid memory
  167.   //
  168.   LPVOID lp = GlobalLock(hGlobal);
  169.   if (lp) {
  170.     if (IsBadReadPtr(lp, 1)) {
  171.       GlobalUnlock(hGlobal);
  172.       return 0;
  173.     }
  174.     GlobalUnlock(hGlobal);
  175.   }
  176.  
  177.   if (hGlobal != 0 && lpMedium->pUnkForRelease != 0) {
  178.     //
  179.     // OLE2NOTE: the callee wants to retain ownership of the data.
  180.     //    this is indicated by passing a non-0 pUnkForRelease.
  181.     //    thus, we will make a copy of the data and release the
  182.     //    callee's copy.
  183.     //
  184.     HGLOBAL hCopy;
  185.     hCopy = OleDuplicateData(hGlobal, cfFormat, GHND|GMEM_SHARE);
  186.     ReleaseStgMedium(lpMedium);
  187.  
  188.     hGlobal = hCopy;
  189.     lpMedium->hGlobal = hCopy;    //!CQ nonamelessunion? u.
  190.     lpMedium->pUnkForRelease = 0;
  191.   }
  192.   return hGlobal;
  193. }
  194.  
  195. //
  196. // Fills and returns a OBJECTDESCRIPTOR structure. The source object will
  197. // offer CF_OBJECTDESCRIPTOR if it is an OLE2 object, CF_OWNERLINK if it
  198. // is an OLE1 object, or CF_FILENAME if it has been copied to the clipboard
  199. // by FileManager.
  200. //
  201. HGLOBAL
  202. TOleDialog::FillObjectDescriptorFromData(LPDATAOBJECT lpDataObject,
  203.                                          LPSTGMEDIUM  lpmedium,
  204.                                          CLIPFORMAT far* lpcfFmt)
  205. {
  206.   CLSID              clsid;
  207.   SIZEL              sizelHim;
  208.   POINTL             pointl;
  209.   LPSTR              lpsz, szFullUserTypeName, szSrcOfCopy, 
  210.                      szClassName, szDocName, szItemName;
  211.   int                nClassName, nDocName, nItemName, nFullUserTypeName;
  212.   LPSTR              szBuf = 0;
  213.   HKEY               hKey = 0;
  214.   DWORD              dw = MaxPathLen;  
  215.   HGLOBAL            hObjDesc;
  216.   HRESULT            hrErr;
  217.  
  218.   //
  219.   // GetData CF_OBJECTDESCRIPTOR format from the object on the clipboard.
  220.   // Only OLE 2 objects on the clipboard will offer CF_OBJECTDESCRIPTOR
  221.   //
  222.   HGLOBAL hMem = GetData(lpDataObject, cfObjectDescriptor, 0, DVASPECT_CONTENT, lpmedium);
  223.  
  224.   if (hMem != 0) {
  225.     *lpcfFmt = cfObjectDescriptor;
  226.     return hMem;
  227.   }
  228.   else if ((hMem = GetData(lpDataObject,  cfOwnerLink, 
  229.                            0, DVASPECT_CONTENT, lpmedium)) != 0) {
  230.     //
  231.     // If CF_OBJECTDESCRIPTOR is not available, i.e. if this is not an
  232.     // OLE2 object, check if this is an OLE 1 object. OLE 1 objects
  233.     // will offer CF_OWNERLINK
  234.     //
  235.     *lpcfFmt = cfOwnerLink;
  236.  
  237.     //
  238.     // CF_OWNERLINK contains 0-terminated strings for class name,
  239.     // document name and item name with two 0 terminating characters
  240.     // at the end
  241.     //
  242.     szClassName = (LPSTR)GlobalLock(hMem);
  243.     nClassName  = strlen(szClassName);
  244.     szDocName   = szClassName + nClassName + 1;
  245.     nDocName    = strlen(szDocName);
  246.     szItemName  = szDocName + nDocName + 1;
  247.     nItemName   = strlen(szItemName);
  248.  
  249.     //
  250.     // Find FullUserTypeName from Registration database using class name
  251.     //
  252.     if (RegOpenKey(HKEY_CLASSES_ROOT, 0, &hKey) != ERROR_SUCCESS)
  253.        goto error;
  254.  
  255.     //
  256.     // Allocate space for szFullUserTypeName & szSrcOfCopy. 
  257.     // Maximum length of FullUserTypeName is MaxKeyLen. 
  258.     // SrcOfCopy is constructed by concatenating FullUserTypeName, 
  259.     // Document Name and ItemName separated by spaces.
  260.     //
  261.     TOleAllocator allocator;
  262.     szBuf = (LPSTR)allocator.Alloc((DWORD)2*MaxKeyLen+nDocName+nItemName+4);
  263.     if (!szBuf)
  264.       goto error;
  265.  
  266.     szFullUserTypeName = szBuf;
  267.     szSrcOfCopy = szFullUserTypeName+MaxKeyLen+1;
  268.  
  269.     //
  270.     // Get FullUserTypeName
  271.     //
  272.     if (::RegQueryValue(hKey, 0, szFullUserTypeName, (LONG*)&dw) != ERROR_SUCCESS)
  273.        goto error;
  274.  
  275.     //
  276.     // Build up SrcOfCopy string from FullUserTypeName, DocumentName & ItemName
  277.     //
  278.     lpsz = szSrcOfCopy;
  279.     lstrcpy(lpsz, szFullUserTypeName);
  280.     nFullUserTypeName = lstrlen(szFullUserTypeName);
  281.     lpsz[nFullUserTypeName]=' ';
  282.     lpsz += nFullUserTypeName+1;
  283.     lstrcpy(lpsz, szDocName);
  284.     lpsz[nDocName] = ' ';
  285.     lpsz += nDocName+1;
  286.     lstrcpy(lpsz, szItemName);
  287.  
  288.     sizelHim.cx = sizelHim.cy = 0;
  289.     pointl.x = pointl.y = 0;
  290.  
  291.     CLSIDFromProgID(OleStr(szClassName), &clsid);
  292.  
  293.     hObjDesc = GetObjectDescriptorData(clsid, DVASPECT_CONTENT, sizelHim,
  294.                                        pointl, 0, szFullUserTypeName,
  295.                                        szSrcOfCopy);
  296.     if (!hObjDesc)
  297.        goto error;
  298.  
  299.   //
  300.   // Check if object is CF_FILENAME
  301.   //
  302.   }
  303.   else if ((hMem = GetData(lpDataObject, cfFileName, 0,  DVASPECT_CONTENT,
  304.                            lpmedium)) != 0) {
  305.     *lpcfFmt = cfFileName;
  306.     lpsz = (LPSTR)GlobalLock(hMem);
  307.     hrErr = GetClassFile(OleStr(lpsz), &clsid);
  308.  
  309.     //
  310.     // OLE2NOTE: if the file does not have an OLE class
  311.     //    associated, then use the OLE 1 Packager as the class of
  312.     //    the object to be created. this is the behavior of
  313.     //    OleCreateFromData API
  314.     //
  315.     if (hrErr != NOERROR)
  316.       CLSIDFromProgID(OleText("Package"), &clsid);
  317.     sizelHim.cx = sizelHim.cy = 0;
  318.     pointl.x = pointl.y = 0;
  319.  
  320.     TOleAllocator allocator;
  321.     szBuf = (LPSTR)allocator.Alloc(MaxKeyLen);
  322.     if (0 == szBuf)
  323.       goto error;
  324.  
  325.     GetUserTypeOfClass(clsid, szBuf, 0);
  326.  
  327.     hObjDesc = GetObjectDescriptorData(clsid, DVASPECT_CONTENT, sizelHim,
  328.                                        pointl, 0, szBuf, lpsz);
  329.     if (!hObjDesc)
  330.       goto error;
  331.   }
  332.   else {
  333.     TRACEX(OwlOleDlg, 1, "Unable to retrieve OBJECTDESCRIPTOR info.");
  334.     goto error;
  335.   }
  336.  
  337.   //
  338.   // Clean up
  339.   //
  340.   if (szBuf)
  341.     TOleAllocator().Free((LPVOID)szBuf);
  342.  
  343.   if (hMem) {
  344.     GlobalUnlock(hMem);
  345.     GlobalFree(hMem);
  346.   }
  347.  
  348.   if (hKey) {
  349.     RegCloseKey(hKey);
  350.   }
  351.  
  352.   return hObjDesc;
  353.  
  354. error:
  355.   if (szBuf)
  356.     TOleAllocator().Free((LPVOID)szBuf);
  357.  
  358.   if (hMem) {
  359.     GlobalUnlock(hMem);
  360.     GlobalFree(hMem);
  361.   }
  362.  
  363.   if (hKey) {
  364.     RegCloseKey(hKey);
  365.   }
  366.  
  367.   return 0;
  368. }
  369.  
  370. //
  371. // Returns the specified AuxUserType from the reg db.
  372. //
  373. uint
  374. TOleDialog::GetAuxUserType(REFCLSID rclsid, WORD wAuxUserType,
  375.                            LPSTR lpszAuxUserType, int cch, HKEY hKey)
  376. {
  377.   bool     fCloseRegDB = false;
  378.   HKEY     hThisKey;
  379.   if (!hKey) {
  380.     if (::RegOpenKey(HKEY_CLASSES_ROOT, 0, &hThisKey) != ERROR_SUCCESS)
  381.       return 0;
  382.     fCloseRegDB = true;
  383.   }
  384.   else {
  385.     hThisKey = hKey;
  386.   }
  387.  
  388.   LPOLESTR lpszCLSID;
  389.   StringFromCLSID(rclsid, &lpszCLSID);
  390.  
  391.   char     szKey[MaxKeyLen];     
  392.   lstrcpy(szKey, "CLSID\\");
  393.   lstrcat(szKey, OleStr(lpszCLSID));
  394.   char     szTemp[32];
  395.   wsprintf(szTemp, "\\AuxUserType\\%d", wAuxUserType);
  396.   lstrcat(szKey, szTemp);
  397.  
  398.   lpszAuxUserType[0] = '\0';
  399.   LONG dw = cch;
  400.   LRESULT lRet = ::RegQueryValue(hThisKey, szKey, lpszAuxUserType, &dw);
  401.  
  402.   if (lRet != ERROR_SUCCESS) {
  403.     dw = 0;
  404.     lpszAuxUserType[0] = '\0';
  405.   }
  406.  
  407.   if (fCloseRegDB)
  408.     RegCloseKey(hThisKey);
  409.  
  410.   TOleAllocator().Free((LPVOID)lpszCLSID);
  411.  
  412.   return (UINT)dw;
  413. }
  414.  
  415. //
  416. //
  417. //
  418. uint
  419. TOleDialog::GetUserTypeOfClass(REFCLSID clsid, char far* lpszUserStr, uint len)
  420. {
  421.   if (!lpszUserStr)
  422.     return 0;
  423.  
  424.   HKEY hKey;
  425.   if (RegOpenKey(HKEY_CLASSES_ROOT, 0, &hKey) != ERROR_SUCCESS)
  426.     return 0;
  427.  
  428.   LPOLESTR lpszClsId;
  429.   bool freeClsId = HRIsOK(StringFromCLSID(clsid, &lpszClsId));
  430.  
  431.   char  szKey[MaxPathLen];
  432.   strcpy(szKey, ::ClsIdStr);
  433.   if (freeClsId)
  434.     strcat(szKey, OleStr(lpszClsId));
  435.  
  436.   LONG buffSize = len;
  437.   LPOLESTR lpszProgId;
  438.   bool  freeProgId = false;
  439.   if (::RegQueryValue(hKey, szKey, lpszUserStr, &buffSize) != ERROR_SUCCESS) {
  440.     //
  441.     // Check for OLE 1.0 class
  442.     //
  443.     if (CoIsOle1Class(clsid)) {
  444.       freeProgId = HRIsOK(ProgIDFromCLSID(clsid, &lpszProgId));
  445.       if (freeProgId) {
  446.         buffSize = len;
  447.         if (::RegQueryValue(hKey, OleStr(lpszProgId),
  448.                           lpszUserStr, &buffSize) != ERROR_SUCCESS)
  449.           buffSize = 0;
  450.       }
  451.     }
  452.   }
  453.  
  454.   TOleAllocator oleAllocator;
  455.   if (freeClsId)
  456.     oleAllocator.Free(lpszClsId);
  457.  
  458.   if (freeProgId)
  459.     oleAllocator.Free(lpszProgId);
  460.  
  461.   RegCloseKey(hKey);
  462.   return (uint)buffSize;
  463. }
  464.  
  465. //
  466. // DoesFileExist
  467. // -------------
  468. //  Tests for the existence via OpenFile [which opens and closes the file]
  469. //  Returns HFILE_ERROR if an error occurs with ofs.nErrCode containing an
  470. //  error value.
  471. //
  472. HFILE
  473. TOleDialog::DoesFileExist(const char* filename, OFSTRUCT& ofs)
  474. {
  475.   //
  476.   // The following check for reserved MS-DOS device names is necessary
  477.   // because OleCreateFromFile() does not perform such check. More
  478.   // information about this issue is available on the MSDN CD, article
  479.   // 'OleCreateFile() Does Not Check for Reserved Names' - PSS ID# Q111015.
  480.   //
  481.   static char *illegalNames[] = {"LPT1", "LPT2", "LPT3",
  482.                                  "COM1", "COM2", "COM3", "COM4",
  483.                                  "CON", "AUX", "PRN"};
  484.   for (int i=0; i<sizeof(illegalNames)/sizeof(illegalNames[0]); i++) {
  485.     if (strcmpi(filename, illegalNames[i]) == 0) {
  486.       memset(&ofs, 0, sizeof(ofs));
  487.       ofs.nErrCode = 0x0002;  // File not found
  488.       return HFILE_ERROR;
  489.     }
  490.   }
  491.  
  492.   return OpenFile(filename, &ofs, OF_EXIST);
  493. }
  494.  
  495. //
  496. // Returns a pointer to the beginning of the nth field of a string -
  497. // Fields are delimited by 'chDelim'
  498. //
  499. LPSTR
  500. TOleDialog::PtrToNthField(LPSTR lpszStr, int nField, char chDelim)
  501. {
  502.   LPSTR lpszField = lpszStr;
  503.   int    cFieldFound = 1;
  504.  
  505.   if (nField == 1)
  506.     return lpszStr;
  507.  
  508.   while(*lpszField) {
  509.     if (*lpszField++ == chDelim) {
  510.       cFieldFound++;
  511.       if (cFieldFound == nField)
  512.         return lpszField;
  513.     }
  514.   }
  515.   return lpszField;
  516. }
  517.  
  518. //
  519. // TOleDialog's Response Table
  520. //
  521. DEFINE_RESPONSE_TABLE1(TOleDialog, TDialog)
  522.   EV_WM_CLOSE,
  523.   EV_COMMAND(IDOK, CmOk),
  524.   EV_COMMAND(IDCANCEL, CmCancel),
  525. END_RESPONSE_TABLE;
  526.  
  527. //
  528. // Registered Clipboard Formats
  529. //
  530. uint16 TOleDialog::cfObjectDescriptor = 0;
  531. uint16 TOleDialog::cfLinkSrcDescriptor= 0;
  532. uint16 TOleDialog::cfEmbedSource      = 0;
  533. uint16 TOleDialog::cfEmbeddedObject   = 0;
  534. uint16 TOleDialog::cfLinkSource       = 0;
  535. uint16 TOleDialog::cfOwnerLink        = 0;
  536. uint16 TOleDialog::cfFileName         = 0;
  537. bool   TOleDialog::cfInit             = false;
  538.  
  539. //
  540. //
  541. //
  542. TOleDialog::TOleDialog(TWindow*        parent,
  543.                        TResId          templateId,
  544.                        const char far* title,
  545.                        TModule*        module)
  546. :
  547.   TDialog(parent, templateId, module),
  548.   ODTitle(title), Font(0)
  549. {
  550.   //
  551.   // Register  Clipboard Formats
  552.   //
  553.   if (!cfInit) {
  554.     cfObjectDescriptor  = (uint16)::RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  555.     cfLinkSrcDescriptor = (uint16)::RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR);
  556.     cfEmbedSource       = (uint16)::RegisterClipboardFormat(CF_EMBEDSOURCE);
  557.     cfEmbeddedObject    = (uint16)::RegisterClipboardFormat(CF_EMBEDDEDOBJECT);
  558.     cfLinkSource        = (uint16)::RegisterClipboardFormat(CF_LINKSOURCE);
  559.     cfOwnerLink         = (uint16)::RegisterClipboardFormat(CF_OWNERLINK);
  560.     cfFileName          = (uint16)::RegisterClipboardFormat(CF_FILENAME);
  561.     cfInit = true;
  562.   }
  563. }
  564.  
  565. //
  566. // Creates non-bold font for static controls and update dialog's title
  567. // if user specified one.
  568. //
  569. void
  570. TOleDialog::SetupWindow()
  571. {
  572.     TDialog::SetupWindow();
  573.  
  574.     //
  575.     // Create non-bold font for text displays
  576.     //
  577.     HFONT   hfont = GetWindowFont();
  578.     LOGFONT lf;
  579.     GetObject(hfont, sizeof(LOGFONT), &lf);
  580.     lf.lfWeight=FW_NORMAL;
  581.     Font = new TFont(&lf);
  582.  
  583.     //
  584.     // Override title if user specified one
  585.     //
  586.     if (ODTitle)
  587.       SetCaption(ODTitle);
  588. }
  589.  
  590. //
  591. // Cleanup Font
  592. //
  593. void
  594. TOleDialog::CleanupWindow()
  595. {
  596.   if (Font) {
  597.     delete Font;
  598.     Font = 0;
  599.   }
  600. }
  601.  
  602. //
  603. // Enables and shows [or disables and hides] a [child] window
  604. //
  605. void
  606. TOleDialog::Activate(TWindow *win, bool activate)
  607. {
  608.   win->Show(activate ? SW_SHOW : SW_HIDE);
  609.   win->EnableWindow(activate);
  610. }
  611.  
  612. //
  613. // Responds to OK button by invoking virtual method prior before chaining
  614. // to base class CmOk if everything's OK - This allows the derived OLE-DLG
  615. // to 'veto' the closure of the dialog.
  616. //
  617. void
  618. TOleDialog::CmOk()
  619. {
  620.   if (OleDlgOk()) {
  621.     TDialog::CmOk();
  622.   }
  623. }
  624.  
  625. //
  626. // Displays a MessageBox informing user of an error resulting
  627. // from a file operation.
  628. //
  629. int
  630. TOleDialog::ErrorWithFile(uint strId, const char* fileName, uint mbFlags)
  631. {
  632.   const int BuffLen = MaxPathLen*2;
  633.   TPointer<char>  pstr1 = new char[BuffLen];
  634.   TPointer<char>  pstr2 = new char[BuffLen];
  635.   TPointer<char>  pstr3 = new char[BuffLen];
  636.  
  637.   if (GetModule()->LoadString(strId, pstr1, BuffLen)) {
  638.     wsprintf((LPSTR)(char*)pstr2, (LPSTR)(char*)pstr1, (LPSTR)fileName);
  639.     GetWindowText((LPSTR)(char*)pstr3, BuffLen);
  640.     return MessageBox(pstr2, pstr3, mbFlags);
  641.   }
  642.  
  643.   return 0;
  644. }
  645.  
  646. //
  647. // Invokes ErrorWithFile [see above] with the appropriate string resource
  648. // Id. based on the Error Code specified.
  649. //
  650. void
  651. TOleDialog::OpenFileError(uint errCode, const char* fileName)
  652. {
  653.   switch (errCode) {
  654.     case  0x0005:   // Access denied
  655.           ErrorWithFile(IDS_CIFILEACCESS, fileName);
  656.           break;
  657.  
  658.     case  0x0020:   // Sharing Violation
  659.           ErrorWithFile(IDS_CIFILESHARE, fileName);
  660.           break;
  661.  
  662.     case  0x0002:   // File not found
  663.     case  0x0003:   // Path not found
  664.           ErrorWithFile(IDS_CIINVALIDFILE, fileName);
  665.           break;
  666.  
  667.     default:        // Other failures
  668.           ErrorWithFile(IDS_CIFILEOPENFAIL, fileName);
  669.           break;
  670.   }
  671. }
  672.  
  673. //
  674. // Displays the standard FileOpen with the 'Browse' caption.
  675. //
  676. bool
  677. TOleDialog::BrowseDlg(char* file, char* initDir, uint filterId, uint32 flags)
  678. {
  679.   //
  680.   // Retrieve filters from resource if specified
  681.   //
  682.   char  filterBuff[256];
  683.   char *filterPtr = 0;
  684.   if (filterId)
  685.     if (GetModule()->LoadString(filterId, filterBuff, sizeof(filterBuff)))
  686.       filterPtr = filterBuff;
  687.  
  688.   //
  689.   // Retrieve dialog's title from resource
  690.   //
  691.   char  titleBuff[128];
  692.   char *titlePtr = 0;
  693.   if (GetModule()->LoadString(IDS_BROWSE, titleBuff, sizeof(titleBuff)))
  694.     titlePtr = titleBuff;
  695.  
  696.   //
  697.   // Create/Init TFileOpenDialog data structure
  698.   //
  699.   TOpenSaveDialog::TData *data;
  700.   data = new TOpenSaveDialog::TData(flags, filterPtr, 0, initDir);
  701.  
  702.   //
  703.   // Execute dialog and return status [copying new filename if necessary]
  704.   //
  705.   TFileOpenDialog fopenDlg(this, *data, 0, titlePtr);
  706.   int ret = fopenDlg.Execute();
  707.  
  708.   if (ret == IDOK)
  709.     strcpyn(file, data->FileName, MaxPathLen);
  710.  
  711.   delete data;
  712.   return (ret == IDOK) ? true : false;
  713. }
  714.  
  715. //
  716. //
  717. //
  718. char far*
  719. TOleDialog ::ChopText(TWindow &ctl, int width, char far* lpch)
  720. {
  721.   //
  722.   // Use client area's width if 0 width specified
  723.   //
  724.   if (!width) {
  725.     TRect rect;
  726.     ctl.GetClientRect(rect);
  727.     width = rect.Width();
  728.   }
  729.  
  730.   //
  731.   // Grab control's font
  732.   //
  733.   HFONT hFont = ctl.GetWindowFont();
  734.   if (!hFont)
  735.     hFont = (HFONT)GetStockObject(SYSTEM_FONT);
  736.   TFont font(hFont);
  737.  
  738.   //
  739.   // Graf control's DC and select font
  740.   //
  741.   TClientDC hdc(ctl);
  742.   hdc.SelectObject(font);
  743.  
  744.   if (GetTextWSize(hdc, lpch) > width) {
  745.     char szPrefix[PrefixSize];
  746.     wsprintf(szPrefix, PrefixFmt, lpch[0], lpch[1], lpch[2]);
  747.     width -= GetTextWSize(hdc, szPrefix);
  748.  
  749.     bool done = false;
  750.     while (!done) {
  751.       while(*lpch  &&  (*lpch != '\\'))
  752.         lpch = AnsiNext(lpch);
  753.       if (*lpch)
  754.         lpch = AnsiNext(lpch);
  755.  
  756.       if (!*lpch  ||  GetTextWSize(hdc, lpch) <= width) {
  757.         if (!*lpch)
  758.           szPrefix[strlen(szPrefix)-1] = 0;
  759.  
  760.         for (int i=strlen(szPrefix)-1; i>=0; --i)
  761.           *--lpch = szPrefix[i];
  762.  
  763.         done = true;
  764.       }
  765.     }
  766.   }
  767.  
  768.   hdc.RestoreFont();
  769.   return lpch;
  770. }
  771.  
  772. //
  773. //
  774. //
  775. int
  776. TOleDialog::GetTextWSize(TDC &dc, char far* lpsz)
  777. {
  778.   TSize size;
  779.   if (dc.GetTextExtent(lpsz, strlen(lpsz), size))
  780.     return size.cx;
  781.   else
  782.     return 0;
  783. }
  784.  
  785. //
  786. //
  787. //
  788. int
  789. TOleDialog::PopupMessage(uint msgId, uint titleId, uint mbFlags)
  790. {
  791.   TPointer<char>  pTitle = new char[LoadStringLen];
  792.   TPointer<char>  pMsg   = new char[LoadStringLen];
  793.  
  794.   GetModule()->LoadString(msgId, pTitle, LoadStringLen);
  795.   GetModule()->LoadString(titleId, pTitle, LoadStringLen);
  796.  
  797.   return MessageBox(pMsg, pTitle, mbFlags);
  798. }
  799.  
  800.  
  801. DEFINE_RESPONSE_TABLE1(TIconImage, TControl)
  802.   EV_WM_PAINT,
  803.   EV_WM_ERASEBKGND,
  804. END_RESPONSE_TABLE;
  805.  
  806. //
  807. //
  808. //
  809. TIconImage::TIconImage(TWindow* parent, int resourceId, TModule* module)
  810.            :TControl(parent, resourceId, module), MetaPict(0)
  811. {}
  812.  
  813. //
  814. //
  815. //
  816. void
  817. TIconImage::GetWindowClass(WNDCLASS& wndclass)
  818. {
  819.   TControl::GetWindowClass(wndclass);
  820.  
  821.   wndclass.hbrBackground = 0;
  822.   wndclass.style = 0;
  823. }
  824.  
  825. //
  826. //
  827. //
  828. bool
  829. TIconImage::SetMetaPict(HGLOBAL metaPict, bool deleteOld)
  830. {
  831.   HGLOBAL oldMeta = MetaPict;
  832.   MetaPict = metaPict;
  833.  
  834.   Invalidate();
  835.   UpdateWindow();
  836.  
  837.   if (deleteOld) {
  838.     if (oldMeta) {
  839.       return TOleMetaPict::Free(oldMeta);
  840.     }
  841.     else {
  842.       TRACEX(OwlOleDlg, 1, "Old handle is 0 and was not deleted");
  843.       return false;
  844.     }
  845.   }
  846.   return true;
  847. }
  848.  
  849. //
  850. //
  851. //
  852. void
  853. TIconImage::EvPaint()
  854. {
  855.   TPaintDC dc(*this);
  856.   TRect clientRect;
  857.   GetClientRect(clientRect);
  858.  
  859.   TOleMetaPict oleMetaPict(MetaPict);
  860.   oleMetaPict.Draw(dc, clientRect, false);
  861. }
  862.  
  863. //
  864. //
  865. //
  866. bool
  867. TIconImage::EvEraseBkgnd(HDC hdc)
  868. {
  869.   HBRUSH  hBrush;
  870. #if defined(BI_PLAT_WIN32)
  871.   hBrush = (HBRUSH)Parent->SendMessage(WM_CTLCOLORDLG, (WPARAM)hdc,
  872.                                        (LPARAM)GetParent());
  873. #else
  874.   hBrush = (HBRUSH)Parent->SendMessage(WM_CTLCOLOR, (WPARAM)hdc,
  875.                                       MAKELPARAM(GetParent(), CTLCOLOR_DLG));
  876. #endif
  877.  
  878.   if (!hBrush)
  879.     return false;
  880.  
  881.   TBrush brush(hBrush);
  882. #if defined(BI_PLAT_WIN16)
  883.   brush.UnrealizeObject();
  884. #endif
  885.  
  886.   TDC dc(hdc);
  887.   dc.SetBrushOrg(0, 0);
  888.  
  889.   TRect rect;
  890.   GetClientRect(rect);
  891.   dc.FillRect(rect, brush);
  892.   return true;
  893. }
  894.  
  895. //
  896. // Constants
  897. //
  898. const long RopDSPDxax = 0x00E20746L;
  899.  
  900. //
  901. //
  902. //
  903. DEFINE_RESPONSE_TABLE1(TResultImage, TControl)
  904.   EV_WM_PAINT,
  905. END_RESPONSE_TABLE;
  906.  
  907. //
  908. // Init variables
  909. //
  910. TResultImage::TResultImage(TWindow* parent, int resourceId, TModule* module)
  911.              :TControl(parent, resourceId, module)
  912. {
  913.   Bitmap = 0;
  914.   ShouldDelete = false;
  915. }
  916.  
  917. //
  918. // Clean up bitmap (if necessary)
  919. //
  920. TResultImage::~TResultImage()
  921. {
  922.   SetBitmap(0);
  923. }
  924.  
  925. //
  926. //
  927. //
  928. void
  929. TResultImage::GetWindowClass(WNDCLASS& wndclass)
  930. {
  931.   TControl::GetWindowClass(wndclass);
  932.  
  933.   wndclass.hbrBackground = 0;
  934.   wndclass.style = CS_VREDRAW | CS_HREDRAW;
  935. }
  936.  
  937. //
  938. //
  939. //
  940. void
  941. TResultImage::SetupWindow()
  942. {
  943.   TControl::SetupWindow();
  944.  
  945.   //
  946.   // Init Result Bitmap
  947.   //
  948.   TResId bmpId;
  949.   TScreenDC screenDC;
  950.   int cx = screenDC.GetDeviceCaps(LOGPIXELSY);
  951.   if (cx <= 72)                 bmpId = IDB_RESULTSEGA;
  952.   if (cx > 72  &&  cx < 120)    bmpId = IDB_RESULTSVGA;
  953.   if (cx >= 120)                bmpId = IDB_RESULTSHIRESVGA;
  954.   SetBitmap(bmpId, TColor::LtCyan, 7, 0);
  955. }
  956.  
  957. //
  958. //
  959. //
  960. void
  961. TResultImage::SetBitmap(TResId bmpId, TColor transparentColor,
  962.                         uint numRows, uint curIndex, TAutoDelete autoDelete)
  963. {
  964.   //
  965.   // Cleanup current bitmap if 'shouldDelete' is enabled
  966.   //
  967.   if (Bitmap  &&  ShouldDelete)
  968.   {
  969.     delete Bitmap;
  970.     Bitmap = 0;
  971.   }
  972.  
  973.   //
  974.   // Retrieve new bitmap if necessary
  975.   //
  976.   if (bmpId != 0)
  977.   {
  978.     ShouldDelete = autoDelete == AutoDelete ? true : false;
  979.     Bitmap = new TBitmap(*GetModule(), bmpId);
  980.  
  981.     NumRows   = numRows;
  982.     CurIndex  = curIndex;
  983.     ClearColor= transparentColor;
  984.  
  985.     CX = Bitmap->Width();
  986.     CY = Bitmap->Height();
  987.  
  988.     if (numRows)
  989.       CY /= numRows;
  990.  
  991.     SetBitmapIndex(curIndex);   // Invalidates the window
  992.   }
  993. }
  994.  
  995. //
  996. //
  997. //
  998. void
  999. TResultImage::SetBitmapIndex(uint curIndex)
  1000. {
  1001.   PRECONDITION(Bitmap);
  1002.   PRECONDITION(curIndex < NumRows);
  1003.  
  1004.   CurIndex = curIndex;
  1005.  
  1006.   //
  1007.   // Force repaint
  1008.   //
  1009.   Invalidate(false);
  1010.   UpdateWindow();
  1011. }
  1012.  
  1013. //
  1014. //
  1015. //
  1016. void
  1017. TResultImage::EvPaint()
  1018. {
  1019.   TPaintDC dc(*this);
  1020.  
  1021.   //
  1022.   // Retrieve background brush of parent
  1023.   //
  1024.   HBRUSH  hBrush = 0;
  1025.  
  1026.   {
  1027.   TClientDC parentDC(*Parent);
  1028. #if defined(BI_PLAT_WIN32)
  1029.   hBrush = (HBRUSH)Parent->SendMessage(WM_CTLCOLORDLG, (WPARAM)(HDC)parentDC,
  1030.                                        (LPARAM)GetParent());
  1031. #else
  1032.   hBrush = (HBRUSH)Parent->SendMessage(WM_CTLCOLOR, (WPARAM)(HDC)parentDC,
  1033.                                       MAKELPARAM(GetParent(), CTLCOLOR_DLG));
  1034. #endif
  1035.   }
  1036.  
  1037.   //
  1038.   // Make our DC's background color match parent's background
  1039.   //
  1040.   if (hBrush)
  1041.   {
  1042.     LOGBRUSH lb;
  1043.     GetObject(hBrush, sizeof(LOGBRUSH), &lb);
  1044.     dc.SetBkColor(TColor(lb.lbColor));
  1045.   }
  1046.  
  1047.   if (!Bitmap)
  1048.     return;
  1049.  
  1050.   //
  1051.   // Destination Coordinates for bitmap: Center bitmap
  1052.   //
  1053.   uint dstX =0, dstY =0;
  1054.   TRect rect;
  1055.   GetClientRect(rect);
  1056.   if ((rect.right + rect.left) > CX)
  1057.     dstX = (rect.right + rect.left - CX)/2;
  1058.   if ((rect.bottom + rect.top) > CY)
  1059.     dstY = (rect.bottom + rect.top - CY)/2;
  1060.  
  1061.   //
  1062.   // Source Coordinates: Offset to appropriate row for source
  1063.   //
  1064.   uint srcX, srcY;
  1065.   srcX = 0;
  1066.   srcY = CY * CurIndex;
  1067.  
  1068.   //
  1069.   // Three intermediate memory DCs
  1070.   //
  1071.   TMemoryDC hdcSrc(dc), hdcMid(dc), hdcMem(dc);
  1072.  
  1073.   //
  1074.   // Select our bitmap in a Source MemDC [for bitblt]
  1075.   //
  1076.   hdcSrc.SelectObject(*Bitmap);
  1077.  
  1078.   //
  1079.   // Create monochrome bitmap for masking
  1080.   //
  1081.   TBitmap bmpMono(hdcMid, CX, CY);
  1082.   hdcMid.SelectObject(bmpMono);
  1083.  
  1084.   //
  1085.   // Create 'middle' bitmap
  1086.   //
  1087.   TBitmap bmpMid(dc, CX, CY);
  1088.   hdcMem.SelectObject(bmpMid);
  1089.  
  1090.   //
  1091.   // Create monochrome mask
  1092.   //
  1093.   TColor bkColor = hdcSrc.SetBkColor(ClearColor);
  1094.   hdcMid.BitBlt(0, 0, CX, CY, hdcSrc, srcX, srcY);
  1095.   hdcSrc.SetBkColor(bkColor);
  1096.  
  1097.   //
  1098.   // Save unmodified image in temporary bitmap
  1099.   //
  1100.   hdcMem.BitBlt(0, 0, CX, CY, hdcSrc, srcX, srcY);
  1101.  
  1102.   //
  1103.   // Create/Select background color brush
  1104.   //
  1105.   TBrush bkBrush(dc.GetBkColor());
  1106.   hdcMem.SelectObject(bkBrush);
  1107.  
  1108.   //
  1109.   // Force conversion of monochrome to stay black & white
  1110.   //
  1111.   hdcMem.SetTextColor(TColor(0));
  1112.   hdcMem.SetBkColor(TColor(255, 255, 255));
  1113.  
  1114.   //
  1115.   // Blt brush where monochrome mask is '1'; Leave destination untouch
  1116.   // where it's '0'.
  1117.   //
  1118.   hdcMem.BitBlt(0, 0, CX, CY, hdcMid, 0, 0, RopDSPDxax);
  1119.   dc.BitBlt(dstX, dstY, CX, CY, hdcMem, 0, 0);
  1120.  
  1121.   //
  1122.   // Restore DC attributes
  1123.   //
  1124.   hdcMem.RestoreBrush();
  1125.   hdcMem.RestoreBitmap();
  1126.   hdcMid.RestoreBitmap();
  1127. }
  1128.