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

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Defines TChangeIconDlg
  6. //----------------------------------------------------------------------------
  7. #define INC_OLE2
  8. #include <owl/owlpch.h>
  9. #include <owl/listbox.h>
  10. #include <owl/radiobut.h>
  11. #include <owl/edit.h>
  12. #include <ocf/ocview.h>
  13. #include <owl/oledlg.h>
  14. #include <bwcc.h>   // for IDHELP
  15.  
  16. //
  17. // OWL OLE Dialog diagnostic group.
  18. //
  19. DIAG_DECLARE_GROUP(OwlOleDlg);
  20.  
  21.  
  22. //
  23. // Class TIconListBox
  24. // ----- ------------
  25. //  OwnerDraw ListBox which displays icons [used by TChangeIconDlg]
  26. //
  27. class _OWLCLASS TIconListBox : public TListBox {
  28.   public:
  29.     TIconListBox(TWindow *parent, int resourceId, TModule* module=0):
  30.     TListBox(parent, resourceId, module){};
  31.  
  32.     void    DrawIcon(DRAWITEMSTRUCT far& drawInfo);
  33.  
  34.     void    ODADrawEntire(DRAWITEMSTRUCT far& drawInfo);
  35.     void    ODAFocus(DRAWITEMSTRUCT far& drawInfo);
  36.     void    ODASelect(DRAWITEMSTRUCT far& drawInfo);
  37.  
  38.     void    MeasureItem(MEASUREITEMSTRUCT far& measureInfo);
  39.     void    DeleteItem(DELETEITEMSTRUCT far& deleteInfo);
  40.  
  41.     int     AddIcon(TIcon&);
  42.     uint    AddIconsFromFile(const char far* fileName);
  43. };
  44.  
  45.  
  46. //
  47. // Specifies each listbox entry's size as slightly bigger than
  48. // the size of an icon
  49. //
  50. void
  51. TIconListBox::MeasureItem(MEASUREITEMSTRUCT far& measureInfo)
  52. {
  53.   measureInfo.itemWidth = GetSystemMetrics(SM_CXICON)+cxIconPad;
  54.   measureInfo.itemHeight= GetSystemMetrics(SM_CYICON)+cyIconPad;
  55. }
  56.  
  57.  
  58. //
  59. // Adds an icon to the listbox
  60. //
  61. int
  62. TIconListBox::AddIcon(TIcon &icon)
  63. {
  64.   return (int)HandleMessage(LB_ADDSTRING, 0, (LPARAM)(HICON)icon);
  65. }
  66.  
  67.  
  68. //
  69. // Extracts icons from the specified file and adds them to the listbox.
  70. // NOTE: Performs no validation of the filename
  71. // Returns number of icons added
  72. //
  73. uint
  74. TIconListBox::AddIconsFromFile(const char far* filename)
  75. {
  76.   int count = 0;
  77.   for(uint i=0; i<0xffff; i++) {
  78.     HICON hicon = ExtractIcon(*GetModule(), filename, i);
  79.     if ((UINT)hicon > 32) {
  80.       TIcon icon(hicon);
  81.       if (AddIcon(icon) != LB_ERR)
  82.         count++;
  83.     }
  84.     else {
  85.       break;
  86.     }
  87.   }
  88.   return count;
  89. }
  90.  
  91.  
  92. //
  93. // Handles deletion of items from the listbox by cleaning up each
  94. // icon inserted.
  95. //
  96. void
  97. TIconListBox::DeleteItem(DELETEITEMSTRUCT far& deleteInfo)
  98. {
  99.   DestroyIcon(HICON(deleteInfo.itemData));
  100. }
  101.  
  102.  
  103. //
  104. // Draws a listbox entry by calling DrawIcon [the itemData field
  105. // is really a HICON inserted earlier in the listbox].
  106. //
  107. void
  108. TIconListBox::DrawIcon(DRAWITEMSTRUCT far& drawInfo)
  109. {
  110.   if ((int)drawInfo.itemID < 0)
  111.     return;
  112.  
  113.   TColor bkColor(GetSysColor(drawInfo.itemState & ODS_SELECTED ?
  114.                              COLOR_HIGHLIGHT : COLOR_WINDOW));
  115.  
  116.   TDC dc(drawInfo.hDC);
  117.   TColor oldBkColor = dc.GetBkColor();
  118.  
  119.   dc.TextRect(drawInfo.rcItem, bkColor);
  120.   dc.DrawIcon(drawInfo.rcItem.left+(cxIconPad/2),
  121.               drawInfo.rcItem.top +(cyIconPad/2),
  122.               TIcon(HICON(drawInfo.itemData)));
  123.  
  124.   dc.SetBkColor(oldBkColor);
  125.  
  126.   if (drawInfo.itemState & ODS_FOCUS)
  127.     dc.DrawFocusRect(drawInfo.rcItem);
  128. }
  129.  
  130.  
  131. //
  132. // Draws a Focus Rect - Called for the selected entry
  133. //
  134. void
  135. TIconListBox::ODAFocus(DRAWITEMSTRUCT far& drawInfo)
  136. {
  137.   TDC dc(drawInfo.hDC);
  138.   dc.DrawFocusRect(drawInfo.rcItem);
  139. }
  140.  
  141.  
  142. void
  143. TIconListBox::ODADrawEntire(DRAWITEMSTRUCT far& drawInfo)
  144. {
  145.   DrawIcon(drawInfo);
  146. }
  147.  
  148.  
  149. void
  150. TIconListBox::ODASelect(DRAWITEMSTRUCT far& drawInfo)
  151. {
  152.   DrawIcon(drawInfo);
  153. }
  154.  
  155.  
  156. //
  157. // Initialize data members of structure used internally by TChangeIconDlg -
  158. // The structure keeps track of the dialog's state.
  159. //
  160. TChangeIconDlg::THelper::THelper()
  161. {
  162.   //
  163.   // Using memset since class is a private PODS.
  164.   //
  165.   memset(this, 0, sizeof(THelper));
  166. }
  167.  
  168.  
  169. DEFINE_RESPONSE_TABLE1(TChangeIconDlg, TOleDialog)
  170.   EV_BN_CLICKED(IDC_CURRENT, CurrentClicked),
  171.   EV_BN_CLICKED(IDC_DEFAULT, DefaultClicked),
  172.   EV_BN_CLICKED(IDC_FROMFILE, FromFileClicked),
  173.   EV_EN_KILLFOCUS(IDC_LABEL, LabelKillFocus),
  174.   EV_CHILD_NOTIFY_ALL_CODES(IDC_FILENAME, FileNameNotification),
  175.   EV_LBN_SETFOCUS(IDC_ICONLIST, IconListSetFocus),
  176.   EV_LBN_SELCHANGE(IDC_ICONLIST, IconListSelChange),
  177.   EV_LBN_DBLCLK(IDC_ICONLIST, IconListDblClk),
  178.   EV_BN_CLICKED(IDC_BROWSE, BrowseClicked),
  179.   EV_BN_CLICKED(IDCANCEL, CmCancel),
  180. END_RESPONSE_TABLE;
  181.  
  182.  
  183. //
  184. // Creates C++ objects to wrap controls
  185. //
  186. TChangeIconDlg::TChangeIconDlg(TWindow* parent,
  187.                                TData&   data,
  188.                                TResId   templateId,
  189.                                const char far* title,
  190.                                TModule* module)
  191.                :TOleDialog(parent,
  192.                            templateId ? templateId : TResId(DLG_CHANGEICON),
  193.                            title,
  194.                            module), Data(data), Helper(*new THelper)
  195. {
  196.   CurrentIcon = new TStatic(this, IDC_CURRENTICON);
  197.   DefaultIcon = new TStatic(this, IDC_DEFAULTICON);
  198.  
  199.   Label       = new TEdit(this, IDC_LABEL, MaxLabelLen);
  200.  
  201.   ResultIcon  = new TStatic(this, IDC_RESULTICON);
  202.   ResultLabel = new TStatic(this, IDC_DOCUMENTNAME);
  203.  
  204.   Current     = new TRadioButton(this, IDC_CURRENT);
  205.   Default     = new TRadioButton(this, IDC_DEFAULT);
  206.   FromFile    = new TRadioButton(this, IDC_FROMFILE);
  207.  
  208.   Help        = new TButton(this, IDHELP);
  209.   Browse      = new TButton(this, IDC_BROWSE);
  210.  
  211.   IconList    = new TIconListBox(this, IDC_ICONLIST);
  212.   FileName    = new TEdit(this, IDC_FILENAME, MaxPathLen);
  213. }
  214.  
  215.  
  216. //
  217. // Clean up dialog
  218. //
  219. TChangeIconDlg::~TChangeIconDlg()
  220. {
  221.   delete &Helper;
  222. }
  223.  
  224.  
  225. //
  226. // Initialize members of TData structure
  227. //
  228. TChangeIconDlg::TData::TData()
  229. {
  230.   Flags = 0;
  231.   MetaPict = 0;
  232.   ClsId = CLSID_NULL;
  233.   IconExe[0] = 0;
  234. }
  235.  
  236.  
  237. //
  238. // Wrapper to set a static control's icon
  239. //
  240. void
  241. TChangeIconDlg::SetIcon(TStatic& win, HICON hIcon)
  242. {
  243.   win.SendMessage(STM_SETICON, (WPARAM)hIcon);
  244. }
  245.  
  246.  
  247. //
  248. // Executes dialog
  249. //
  250. int
  251. TChangeIconDlg::DoExecute()
  252. {
  253.   return TDialog::DoExecute();
  254. }
  255.  
  256.  
  257. //
  258. // Performs initialization of ChangeIcon Dialog.
  259. //
  260. void
  261. TChangeIconDlg::SetupWindow()
  262. {
  263.   TOleDialog::SetupWindow();
  264.  
  265.   TModule *module = GetModule();
  266.  
  267.   //
  268.   // Copy Info from user
  269.   //
  270.   Helper.Flags = Data.Flags;
  271.  
  272.   //
  273.   // Extract info about MetaFile icon
  274.   //
  275.   TOleMetaPict metaPict(Data.MetaPict);
  276.  
  277.   metaPict.ExtractIconSource(Helper.File, Helper.IconIndex);
  278.   metaPict.ExtractLabel(Helper.Label);
  279.   Helper.CurIcon = metaPict.ExtractIcon(*GetModule());
  280.  
  281.   //
  282.   // Set Control Font
  283.   //
  284.   if (Font)
  285.     ResultLabel->SetWindowFont(*Font, false);
  286.  
  287.   //
  288.   // Handle Help button display
  289.   //
  290.   if (!(Helper.Flags & ciShowHelp))
  291.     Activate(Help, false);
  292.  
  293.   //
  294.   // Init control displays
  295.   //
  296.   FileName->SetText(Helper.File);
  297.   Label->SetText(Helper.Label);
  298.   ResultLabel->SetText(Helper.Label);
  299.  
  300.   //
  301.   // Use IconExe as IconFile if requested
  302.   //
  303.   Helper.DefIcon = 0;
  304.   if (Helper.Flags & ciUseIconExe) {
  305.     Helper.DefIcon = ExtractIcon(*module, Data.IconExe, 0);
  306.     if (Helper.DefIcon) {
  307.       strcpy(Helper.DefIconFile, Data.IconExe);
  308.       Helper.DefIconIndex = 0;
  309.     }
  310.   }
  311.  
  312.   if (!Helper.DefIcon) {
  313.     HGLOBAL metaPict = GetIconFromClass(Data.ClsId, 0, TRUE);
  314.     if (metaPict) {
  315.       TOleMetaPict defMetaPict(metaPict, AutoDelete);
  316.  
  317.       Helper.DefIcon = defMetaPict.ExtractIcon(*GetModule());
  318.       defMetaPict.ExtractIconSource(Helper.DefIconFile,
  319.                                     Helper.DefIconIndex);
  320.     }
  321.   }
  322.  
  323.   //
  324.   // Init Icon Displays
  325.   //
  326.   SetIcon(*CurrentIcon, Helper.CurIcon);
  327.   SetIcon(*DefaultIcon, Helper.DefIcon);
  328.   SetIcon(*ResultIcon, Helper.CurIcon);
  329.  
  330.   //
  331.   // Adjust listbox dimensions
  332.   //
  333.   int listHeight = GetSystemMetrics(SM_CYICON)+
  334.                    GetSystemMetrics(SM_CYHSCROLL)+
  335.                    GetSystemMetrics(SM_CYBORDER)*2+
  336.                    cyIconPad;
  337.   TRect lRect;
  338.   IconList->GetClientRect(lRect);
  339.   IconList->SetWindowPos(0, 0, 0, lRect.right, listHeight,
  340.                          SWP_NOMOVE|SWP_NOZORDER);
  341.   IconList->SetColumnWidth(GetSystemMetrics(SM_CXICON)+cxIconPad);
  342.  
  343.   TRect gRect;
  344.   IconList->GetWindowRect(lRect);
  345.   //! BB Window may need resizing
  346.  
  347.   //
  348.   // Select appropriate RadioButton
  349.   //
  350.   if (FillIconList(Helper.File)) {
  351.     IconList->SetSelIndex(Helper.IconIndex);
  352.   }
  353.   if (Helper.Flags & ciSelectCurrent) {
  354.     CheckRadioButton(IDC_CURRENT, IDC_FROMFILE, IDC_CURRENT);
  355.   }
  356.   else {
  357.     uint id = (Helper.Flags & ciSelectFromFile) ? IDC_FROMFILE : IDC_DEFAULT;
  358.     CheckRadioButton(IDC_CURRENT, IDC_FROMFILE, id);
  359.   }
  360. }
  361.  
  362.  
  363. //
  364. // Called when user selects 'OK'
  365. //
  366. bool
  367. TChangeIconDlg::OleDlgOk()
  368. {
  369.   char file[MaxPathLen];
  370.   FileName->GetText(file, sizeof(file));
  371.  
  372.   //
  373.   // If the file name has changed we'll simply update the listbox instead
  374.   // of closing the dialog
  375.   //
  376.   if (strcmpi(Helper.File, file)) {
  377.     strcpy(Helper.File, file);
  378.     FillIconList(Helper.File);
  379.     UpdateResultIcon(ciSelectFromFile);
  380.     return false;
  381.   }
  382.  
  383.   //
  384.   // Validate filename if 'SelectFromFile'
  385.   //
  386.   if (Helper.Flags & ciSelectFromFile) {
  387.     OFSTRUCT ofs;
  388.     if (DoesFileExist(Helper.File, ofs)==HFILE_ERROR) {
  389.       OpenFileError(ofs.nErrCode, Helper.File);
  390.       FileName->SetFocus();
  391.       FileName->SetSelection(0, -1);
  392.       return false;
  393.     }
  394.   }
  395.  
  396.   //
  397.   // Set Focus to OK button
  398.   //
  399.   if (GetFocus() != GetDlgItem(IDOK))
  400.     ::SetFocus(GetDlgItem(IDOK));
  401.  
  402.   //
  403.   //
  404.   //
  405.   HICON hIcon = (HICON)ResultIcon->SendMessage(STM_GETICON);
  406.   LPSTR lpsz  = Helper.File;
  407.  
  408.   //
  409.   // Retrieve default information (if Default)
  410.   //
  411.   if (Helper.Flags & ciSelectDefault) {
  412.     lpsz = Helper.DefIconFile;
  413.     Helper.IconIndex = Helper.DefIconIndex;
  414.     hIcon = Helper.DefIcon;
  415.   }
  416.  
  417.   //
  418.   // Extract current icon source (if Current)
  419.   //
  420.   if (Helper.Flags & ciSelectCurrent) {
  421.     TOleMetaPict metaPict(Data.MetaPict);
  422.     metaPict.ExtractIconSource(lpsz, Helper.IconIndex);
  423.   }
  424.  
  425.   //
  426.   // Retrieve filename and index (if FromFile)
  427.   //
  428.   if (Helper.Flags & ciSelectFromFile) {
  429.     FileName->GetText(lpsz, MaxPathLen);
  430.     Helper.IconIndex = IconList->GetSelIndex();
  431.   }
  432.  
  433.   //
  434.   // Retrieve label to make new metafile
  435.   //
  436.   char label[MaxLabelLen];
  437.   Label->GetText(label, sizeof(label));
  438.  
  439.   //
  440.   // Create new metafile
  441.   //
  442.   HGLOBAL hMetaPict = OleMetafilePictFromIconAndLabel(hIcon, label, lpsz,
  443.                                                       Helper.IconIndex);
  444.  
  445.   //
  446.   // Free metafile passed in
  447.   //
  448.   TOleMetaPict::Free(Data.MetaPict);
  449.  
  450.   //
  451.   // Return new metafile to user along with flags
  452.   //
  453.   Data.MetaPict = hMetaPict;
  454.   Data.Flags    = Helper.Flags;
  455.   return true;
  456. }
  457.  
  458.  
  459. //
  460. //
  461. //
  462. void
  463. TChangeIconDlg::CleanupWindow()
  464. {
  465.   //
  466.   // Make sure that icons are properly destroyed
  467.   // (this takes care of destroying the [fromFile] icon)
  468.   //
  469.   IconList->ClearList();
  470.  
  471.   //
  472.   // Destroy Current Icon
  473.   //
  474.   HICON hIcon = (HICON)CurrentIcon->SendMessage(STM_GETICON);
  475.   if (hIcon)
  476.     DestroyIcon(hIcon);
  477.  
  478.   //
  479.   // Destroy the Default Icon
  480.   //
  481.   hIcon = (HICON)DefaultIcon->SendMessage(STM_GETICON);
  482.   if (hIcon)
  483.     DestroyIcon(hIcon);
  484.  
  485.   TOleDialog::CleanupWindow();
  486. }
  487.  
  488.  
  489. //
  490. // Fills the Icon ListBox with icons extracted from the specified filename
  491. //
  492. uint
  493. TChangeIconDlg::FillIconList(const char *fileName)
  494. {
  495.   uint numIcons = 0;
  496.  
  497.   //
  498.   // Clear listbox (which destroys currently extracted icons)
  499.   //
  500.   IconList->ClearList();
  501.  
  502.   //
  503.   // Check for !NULL filename
  504.   //
  505.   if (!fileName || strlen(fileName) == 0)
  506.     return 0;
  507.  
  508.   //
  509.   // Enable Wait cursor and Clear List
  510.   //
  511.   HCURSOR oldCursor = HourGlassOn();
  512.  
  513.   //
  514.   // Validate filename
  515.   //
  516.   OFSTRUCT ofs;
  517.   if (DoesFileExist(fileName, ofs) != HFILE_ERROR) {
  518.     //
  519.     // Check that indeed there are icons in the file
  520.     //
  521.     HICON hIcon = ExtractIcon(*GetModule(), fileName, 0);
  522.     if ((uint)hIcon > 32) {
  523.       //
  524.       // Clean up the extracted icon
  525.       //
  526.       DestroyIcon(hIcon);
  527.  
  528.       //
  529.       // Pass name to listbox for grunt work and for listbox to update
  530.       //
  531.       IconList->SetRedraw(false);
  532.       numIcons = IconList->AddIconsFromFile(fileName);
  533.       IconList->SetRedraw(true);
  534.       IconList->Invalidate(true);
  535.       IconList->SetSelIndex(0);
  536.     }
  537.     else {
  538.       ErrorWithFile(IDS_CINOICONSINFILE, fileName);
  539.     }
  540.   }
  541.   else {
  542.     OpenFileError(ofs.nErrCode, fileName);
  543.   }
  544.  
  545.   HourGlassOff(oldCursor);
  546.   return numIcons;
  547. }
  548.  
  549.  
  550. void
  551. TChangeIconDlg::UpdateResultIcon(TChangeIconFlags flag)
  552. {
  553.   PRECONDITION(flag == ciSelectCurrent ||
  554.                flag == ciSelectDefault ||
  555.                flag == ciSelectFromFile);
  556.  
  557.   Helper.Flags &= ~(ciSelectCurrent | ciSelectDefault | ciSelectFromFile);
  558.  
  559.   long lval = LB_ERR;
  560.  
  561.   if (flag == ciSelectCurrent)
  562.     lval = CurrentIcon->SendMessage(STM_GETICON);
  563.   else if (flag == ciSelectDefault)
  564.     lval = DefaultIcon->SendMessage(STM_GETICON);
  565.   else if (flag == ciSelectFromFile) {
  566.     int index = IconList->GetSelIndex();
  567.     if (index != LB_ERR)
  568.       IconList->HandleMessage(LB_GETTEXT, index, (LPARAM)(LPLONG)&lval);
  569.     else
  570.       lval = DefaultIcon->SendMessage(STM_GETICON);
  571.   }
  572.  
  573.   if (lval != LB_ERR)
  574.     SetIcon(*ResultIcon, (HICON)lval);
  575. }
  576.  
  577.  
  578. void
  579. TChangeIconDlg::CurrentClicked()
  580. {
  581.   UpdateResultIcon(ciSelectCurrent);
  582. }
  583.  
  584.  
  585. void
  586. TChangeIconDlg::DefaultClicked()
  587. {
  588.   UpdateResultIcon(ciSelectDefault);
  589. }
  590.  
  591.  
  592. void
  593. TChangeIconDlg::FromFileClicked()
  594. {
  595.   UpdateResultIcon(ciSelectFromFile);
  596. }
  597.  
  598.  
  599. void
  600. TChangeIconDlg::LabelKillFocus()
  601. {
  602.   char str[MaxPathLen];
  603.   Label->GetText(str, sizeof(str));
  604.   ResultLabel->SetText(str);
  605. }
  606.  
  607.  
  608. void
  609. TChangeIconDlg::FileNameNotification(uint)
  610. {
  611.   char str[MaxPathLen];
  612.   FileName->GetText(str, sizeof(str));
  613.   if (strcmpi(Helper.File, str)) {
  614.     IconList->SetSelIndex(-1);
  615.     CheckRadioButton(IDC_CURRENT, IDC_FROMFILE, IDC_FROMFILE);
  616.   }
  617. }
  618.  
  619.  
  620. //
  621. // If the filename has changed when the IconListBox gains focus,
  622. // the list is refilled and the result icon updated.
  623. //
  624. void
  625. TChangeIconDlg::IconListSetFocus()
  626. {
  627.   char str[MaxPathLen];
  628.   FileName->GetText(str, sizeof(str));
  629.   if (strcmpi(Helper.File, str)) {
  630.     strcpy(Helper.File, str);
  631.     FillIconList(Helper.File);
  632.     UpdateResultIcon(ciSelectFromFile);
  633.   }
  634. }
  635.  
  636.  
  637. //
  638. // Updates result icon if listbox selection changes
  639. //
  640. void
  641. TChangeIconDlg::IconListSelChange()
  642. {
  643.   UpdateResultIcon(ciSelectFromFile);
  644. }
  645.  
  646.  
  647. //
  648. // A double click on the IconListBox is treated as if the 'OK' button
  649. // had been clicked
  650. //
  651. void
  652. TChangeIconDlg::IconListDblClk()
  653. {
  654.   SendNotification(IDOK, BN_CLICKED, GetDlgItem(IDOK));
  655. }
  656.  
  657.  
  658. //
  659. // Allows user to browse for a file from which icons can be extracted
  660. //
  661. void
  662. TChangeIconDlg::BrowseClicked()
  663. {
  664.   //
  665.   // Save a copy of filename
  666.   //
  667.   char file[MaxPathLen];
  668.   FileName->GetText(file, sizeof(file));
  669.  
  670.   //
  671.   // Build flags
  672.   //
  673.   DWORD flags = OFN_FILEMUSTEXIST;
  674.   if (Data.Flags & ciShowHelp)
  675.     flags |= OFN_SHOWHELP;
  676.  
  677.   //
  678.   // Display OpenFile dialog
  679.   //
  680.   if (BrowseDlg(Helper.File, 0, IDS_ICONFILTERS, flags)) {
  681.     //
  682.     // If filename has changed, update display
  683.     //
  684.     if (strcmpi(file, Helper.File)) {
  685.       CheckRadioButton(IDC_CURRENT, IDC_FROMFILE, IDC_FROMFILE);
  686.       FileName->SetText(Helper.File);
  687.       FillIconList(Helper.File);
  688.       UpdateResultIcon(ciSelectFromFile);
  689.     }
  690.   }
  691. }
  692.  
  693.