home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / dragdrop.pak / DRAGDROP.CPP next >
C/C++ Source or Header  |  1997-07-23  |  10KB  |  332 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //
  4. //
  5. //   Drag and Drop example in OWL
  6. //
  7. //   This is a code example using the Drag and Drop feature in
  8. //   Windows 3.1 with OWL.  The example shows how to drop files
  9. //   into the client area of the main window and then print
  10. //   out the file names that were dropped in the client area.
  11. //   TMyWindow maintains this information in a List of Lists.
  12. //   Each sub List is a set of files that were dropped.  The code
  13. //   is well commented with Steps to follow the creation of the
  14. //   application as well as comments for common pitfalls and
  15. //   important lines of code that affect the performance of your
  16. //   application.
  17. //----------------------------------------------------------------------------
  18. #include <owl\owlpch.h>
  19. #include <owl\applicat.h>
  20. #include <owl\window.h>
  21. #include <owl\framewin.h>
  22. #include <owl\dc.h>
  23. #include <stdio.h>
  24. #include <dir.h>
  25. #include <classlib\bags.h>
  26.  
  27. char HelpText[]=
  28.   "\n\r"
  29.   "This application must be run under Windows 3.1 or later.\n\r "
  30.   "Bring up the Windows File Manager. Select a file with\n\r "
  31.   "the left mouse button and keep the button down.\n\r "
  32.   "Now drag the mouse over until it is on top of the drag\n\r "
  33.   "n' drop window client area. Now release the left mouse\n\r"
  34.   "button. You have just dragged and dropped a file. To\n\r "
  35.   "drag a group of files, select the group with the Shift\n\r "
  36.   "and arrow keys and then repeat the previous directions.";
  37.  
  38.  
  39. //----------------------------------------------------------------------------
  40.  
  41. // TFileDrop class Maintains information about a dropped file,
  42. // its name, where it was dropped, and whether or not it
  43. // was in the client area
  44. //
  45. class TFileDrop {
  46.   public:
  47.     // Redefine all the pure virtual functions that make Object abstract.
  48.     //
  49.     operator == (const TFileDrop& other) const {return this == &other;}
  50.  
  51.     char*  FileName;
  52.     TPoint Point;
  53.     BOOL   InClientArea;
  54.  
  55.     HICON  Icon;
  56.     BOOL   DefIcon;
  57.  
  58.     TFileDrop(char*, TPoint&, BOOL, TModule* module);
  59.     ~TFileDrop();
  60.     char* WhoAmI();
  61. };
  62.  
  63. typedef TIBagAsVector<TFileDrop> TFileList;
  64. typedef TIBagAsVectorIterator<TFileDrop> TFileListIter;
  65. typedef TBagAsVector<TFileList*> TFileListList;
  66. typedef TBagAsVectorIterator<TFileList*> TFileListListIter;
  67.  
  68. TFileDrop::TFileDrop(char* fileName, TPoint& p, BOOL inClient, TModule* module)
  69. {
  70.   char  exePath[MAXPATH];
  71.  
  72.   exePath[0] = 0;
  73.   FileName = strcpy(new char[strlen(fileName)+1], fileName);
  74.   Point = p;
  75.   InClientArea = inClient;
  76.  
  77.   Icon = (WORD)FindExecutable(FileName, ".\\", exePath) <= 32 ? 0 :
  78.           ::ExtractIcon(*module, exePath, 0);
  79.  
  80.   // Use a question mark if couldn't get the icon from the executable.
  81.   //
  82.   if ((WORD)Icon <= 1) {  // 0=no icons in exe,  1=not an exe
  83.     Icon = LoadIcon(0, (WORD)Icon == 1 ? IDI_APPLICATION : IDI_QUESTION);
  84.     DefIcon = TRUE;
  85.  
  86.   } else
  87.     DefIcon = FALSE;
  88.  
  89. }
  90.  
  91. TFileDrop::~TFileDrop()
  92. {
  93.   delete FileName;
  94.   if (!DefIcon)    // Don't call FreeResource() on the '?' icon
  95.     FreeResource(Icon);
  96. }
  97.  
  98. char*
  99. TFileDrop::WhoAmI()
  100. {
  101.   static char buffer[80];
  102.   sprintf(buffer, "File: %s (%d,%d) InClient: %d", FileName, Point.x, Point.y,
  103.           InClientArea);
  104.   return buffer;
  105. }
  106.  
  107. //----------------------------------------------------------------------------
  108.  
  109. static void DoDelete(TFileList*& list, void*) {
  110.   delete list;
  111. }
  112.  
  113. class TMyWindow : public TWindow {
  114.   public:
  115.     TMyWindow();
  116.  
  117.   protected:
  118.     void SetupWindow();
  119.     void CleanupWindow();
  120.     void Paint(TDC&, BOOL, TRect&);
  121.  
  122.     //----------------------------------------------------------------
  123.     // Step 2:
  124.     // Dispatch a message to WM_DROPFILES
  125.     //
  126.     void EvDropFiles(TDropInfo);
  127.     void EvSize(UINT, TSize&) { Invalidate(); }
  128.     void CmHowTo() { GetHelp = TRUE; Invalidate(); }
  129.     void CmView() { GetHelp = FALSE; Invalidate(); }
  130.     void CmClear() {
  131.         GetHelp = FALSE;
  132.         AllFiles->ForEach(DoDelete, 0);
  133.         AllFiles->Flush();
  134.         Invalidate();
  135.     }
  136.     void CmAbout() {
  137.         MessageBox("DRAG n' DROP\nWritten using ObjectWindows\n"
  138.                    "Copyright (c) 1991, 1993 Borland", "ABOUT BOX", MB_OK);
  139.     }
  140.  
  141.   protected:
  142.     TFileListList*  AllFiles;
  143.                    // Each Object in the list will also be a list.
  144.                    // These lists will contain the names of the files
  145.                    // that have been dragged & dropped in a group.
  146.   private:
  147.     BOOL GetHelp;
  148.  
  149.   DECLARE_RESPONSE_TABLE(TMyWindow);
  150. };
  151.  
  152. DEFINE_RESPONSE_TABLE1(TMyWindow, TWindow)
  153.   EV_WM_SIZE,
  154.   EV_WM_DROPFILES,
  155.   EV_COMMAND(101, CmHowTo),
  156.   EV_COMMAND(102, CmView),
  157.   EV_COMMAND(103, CmClear),
  158.   EV_COMMAND(104, CmAbout),
  159. END_RESPONSE_TABLE;
  160.  
  161.  
  162. //----------------------------------------------------------------
  163. // AllFiles of TMyWindow is a linked list of Lists.
  164. // Each List in the linked list will contain the file names
  165. // that were received during a WM_DROPFILES messages.
  166. // The following declarations are to build up the object
  167. // which will desribe an individual file that was droped
  168. // during one of these messages.
  169. // Since these objects are derived from Object, they
  170. // can be inserted into a List.
  171. //----------------------------------------------------------------
  172.  
  173. TMyWindow::TMyWindow() : TWindow(0, 0, 0)
  174. {
  175.   AllFiles = new TFileListList;
  176.   GetHelp = TRUE;
  177. }
  178.  
  179. void
  180. TMyWindow::SetupWindow()
  181. {
  182.   TWindow::SetupWindow();
  183.  
  184.   //----------------------------------------------------------------
  185.   // Step 1:
  186.   // calling DragAcceptFiles.  If you pass FALSE, you're saying
  187.   // I don't accept them anymore.
  188.   // WARNING: Don't do this in the constructor!  HWindow is NOT
  189.   // valid at that point.
  190.   //
  191.   DragAcceptFiles(TRUE);
  192. }
  193.  
  194. void
  195. TMyWindow::CleanupWindow()
  196. {
  197.   //----------------------------------------------------------------
  198.   // Step 9:
  199.   // Don't accept files anymore
  200.   //
  201. //  DragAcceptFiles(FALSE);
  202.   delete AllFiles;
  203.   TWindow::CleanupWindow();
  204. }
  205.  
  206. //----------------------------------------------------------------
  207. //  Step 3:
  208. //  Retrieve a handle to an internal data structure in
  209. //  SHELL.DLL.  Get the info out of it.
  210. //
  211. void
  212. TMyWindow::EvDropFiles(TDropInfo drop)
  213. {
  214.   GetHelp = FALSE;
  215.  
  216.   //----------------------------------------------------------------
  217.   // Step 4:
  218.   // Find out how many files are dropped,
  219.   //
  220.   int totalNumberOfFiles = drop.DragQueryFileCount();
  221.  
  222.   TFileList* files = new TFileList;
  223.  
  224.   for (WORD i = 0; i < totalNumberOfFiles; i++) {
  225.     //----------------------------------------------------------------
  226.     // Step 5:
  227.     // Get the length of a filename.
  228.     //
  229.     UINT  fileLength = drop.DragQueryFileNameLen(i)+1;
  230.     char* fileName = new char[fileLength];
  231.  
  232.     //----------------------------------------------------------------
  233.     // Step 6:
  234.     // Copy a file name.   Tell DragQueryFile the file
  235.     // your interested in (i) and the length of your buffer.
  236.     // NOTE: Make sure that the length is 1 more than the filename
  237.     // to make room for the null charater!
  238.     //
  239.     drop.DragQueryFile(i, fileName, fileLength);
  240.  
  241.     //----------------------------------------------------------------
  242.     // Step 7:
  243.     // Getting the file dropped. The location is relative to your
  244.     // client coordinates, and will have negative values if dropped in
  245.     // the non client parts of the window.
  246.     //
  247.     // DragQueryPoint copies that point where the file was dropped
  248.     // and returns whether or not the point is in the client area.
  249.     // Regardless of whether or not the file is dropped in the client
  250.     // or non-client area of the window, you will still receive the
  251.     // file name.
  252.     //
  253.     TPoint point;
  254.     BOOL   inClientArea = drop.DragQueryPoint(point);
  255.     files->Add(new TFileDrop(fileName, point, inClientArea, GetModule()));
  256.   }
  257.   AllFiles->Add(files);  // Add this sublist of dropped files to the big list.
  258.  
  259.   //----------------------------------------------------------------
  260.   // Step 8:
  261.   // Release the memory shell allocated for this handle
  262.   // with DragFinish.
  263.   // NOTE: This is a real easy step to forget and could
  264.   // explain memory leaks and incorrect program performance.
  265.   //
  266.   drop.DragFinish();
  267.  
  268.   Invalidate();  // Make sure we repaint.
  269. }
  270.  
  271. void
  272. TMyWindow::Paint(TDC& dc, BOOL, TRect&)
  273. {
  274.   if (GetHelp) {
  275.     TRect rect;
  276.     GetClientRect(rect);
  277.     dc.DrawText(HelpText, strlen(HelpText), rect,
  278.                 DT_NOCLIP|DT_CENTER|DT_WORDBREAK);
  279.   } else {
  280.     dc.SetBkMode(TRANSPARENT);
  281.  
  282.     // get a list iterator for the main list.
  283.     //
  284.     TFileListListIter allFileI(*AllFiles);
  285.     int i = 0;
  286.  
  287.     // for each element in the main list that is not 0, get a
  288.     // list iterator for that element, which is itself a list,
  289.     // call it a sub list
  290.     //
  291.     while (allFileI) {
  292.       if (allFileI.Current()) {
  293.         TFileListIter subListI(*allFileI.Current());
  294.         // for each element in the sub list, get the string
  295.         // which describes it, we know these elements are
  296.         // instances of the TFileDrop class
  297.         //
  298.         while (subListI) {
  299.           char* str = subListI.Current()->WhoAmI();
  300.           DrawIcon(dc, 10, 20*i, subListI.Current()->Icon);
  301.           dc.TextOut(TPoint(60, 20*i), str);
  302.           i += 2;
  303.           subListI++;
  304.         }
  305.         allFileI++;
  306.       }
  307.     }
  308.   }
  309. }
  310.  
  311. //----------------------------------------------------------------------------
  312.  
  313. class TMyApp : public TApplication {
  314.   public:
  315.     TMyApp() : TApplication() {}
  316.     void InitMainWindow();
  317. };
  318.  
  319. void
  320. TMyApp::InitMainWindow()
  321. {
  322.   MainWindow = new TFrameWindow(0, "Drag & Drop Example", new TMyWindow);
  323.   MainWindow->AssignMenu("DRAGMENU");
  324.   MainWindow->EnableKBHandler();
  325. }
  326.  
  327. int
  328. OwlMain(int /*argc*/, char* /*argv*/ [])
  329. {
  330.   return TMyApp().Run();
  331. }
  332.