home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 10.ddi / DRAG.ZIP / DRAGDROP.C next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  14.2 KB  |  449 lines

  1. // (C) Copyright 1992 by Borland International
  2. //
  3. // DragDrop.c - Drag and Drop example in C
  4.  
  5. // Beginning of file dragdrop.c
  6.  
  7. /* --------------------------------------------------------------
  8.     This is a code example using the Drag and Drop feature in
  9.     Windows 3.1 with C.  The example shows how to drop files
  10.     into the client area of the main window and then print out
  11.     the file names only if they were dropped in the client area.
  12.     The list of files will be kept in a linked list of structures.
  13.     The code is well commented with Steps to follow the creation
  14.     of the application as well as comments for common pitfalls
  15.     and important lines of code that affect the performance of
  16.     your application.
  17.  --------------------------------------------------------------- */
  18.  
  19. char HelpText[]=
  20. "\n\rThis application must be run under Windows 3.1.\n\r \
  21. Bring up the Windows 3.1 File Manager.  Select a file\n\r \
  22. with the left mouse button and keep the button down.\n\r \
  23. Now drag the mouse over until it is on top of the drag\n\r \
  24. n' drop window client area.  Now release the left mouse\n\r \
  25. button.  You have just dragged and dropped a file.  To\n\r \
  26. drag a group of files, select the group with the Shift\n\r \
  27. and arrow keys and then repeat the previous directions.";
  28.  
  29. #define STRICT    // define STRICT to provide maximum type safety
  30.                     // as defined by Microsoft
  31.  
  32. #include <windows.h>
  33. #include <string.h>
  34. #include <alloc.h>
  35. /***************************************************************
  36.     Step 0:
  37.     This is the header file which declares the Drag and Drop
  38.     functions. The functions are in SHELL.DLL
  39. ****************************************************************/
  40. #include <shellapi.h>
  41.  
  42. long FAR PASCAL _export MainWndProc(HWND, unsigned, WORD, LONG);
  43. void AddFiles(HWND, struct List*);
  44.  
  45. // Definition of structure types for Linked list of files
  46. struct FileList {
  47.     char *lpFileName;    // Name of dragged file
  48.     int x, y;            // Position in client area dropped
  49.     BOOL inClient;        // Dropped in client Flag
  50.     struct FileList *Next;    // Points to next file in group dragged
  51. };
  52. struct List {
  53.     struct List *Next;        // Points to next node in List
  54.     struct FileList *FLptr;    // Points to Filelist(s)
  55. };
  56.  
  57. // Global variables
  58. HINSTANCE hInst;    // current instance
  59. struct List *liAllFiles;    // Pointer to main list of files
  60. BOOL GetHelp;
  61.  
  62.  
  63. /********************************************************************/
  64. void FileDrop( struct FileList* ptr, char *FileName , int px, int py,
  65.                 BOOL inClientarea )
  66. {
  67.     ptr->lpFileName =(char*)malloc(strlen( FileName ) + 1 );
  68.     strcpy( ptr->lpFileName, FileName );
  69.     ptr->x = px;
  70.     ptr->y = py;
  71.     ptr->inClient = inClientarea;
  72.     ptr->Next=NULL;
  73. }
  74.  
  75. char *WhoAmI(struct FileList *ptr)
  76. {
  77.     static char buffer[ 80 ];
  78.  
  79.     wsprintf( buffer, "File: %s [ %d , %d ] inClient: %d",
  80.              (LPSTR)ptr->lpFileName, ptr->x , ptr->y, ptr->inClient );
  81.  
  82. //WARNING!!:  Serious problem recognized:
  83.         //In the small model, without the typecast,
  84.         //lpFileName was two bytes on the stack of which
  85.         //wsprintf took 4.
  86.  
  87.     return buffer;
  88. }
  89.  
  90.  
  91. void WMDropFiles( WORD WParam, HWND hWnd)
  92. /*********************************************************
  93.     Step 3:
  94.     Retrieve a handle to an internal data structure in
  95.     SHELL.DLL.  Get the info of the files out of it.
  96. **********************************************************/
  97. {
  98.     struct FileList *FLptr=NULL, *FLCurrent=NULL, *FLHead=NULL;
  99.     struct List *liFiles;
  100.     int TotalNumberOfFiles;
  101.     int nFileLength;
  102.     char *pszFileName;
  103.     POINT pPoint;
  104.     BOOL inClientArea;
  105.     int i;
  106. /********************************************************
  107.     Step 4:
  108.     Identify the handle
  109. *********************************************************/
  110.     HDROP hDrop = (HDROP)WParam;
  111.                 //msg.WParam contains the Handle to the
  112.                 //internal data structure which has
  113.                 //information about the dropped file(s)
  114.  
  115. /****************************************************************
  116.     Step 5:
  117.     Find out total number of files dropped, by passing 0xFFFF for
  118.     index parameter to DragQueryFile
  119. *****************************************************************/
  120.     TotalNumberOfFiles = DragQueryFile( hDrop , 0xFFFF, NULL, 0 );
  121.     GetHelp=FALSE;
  122.  
  123.     liFiles =(struct List*)malloc(sizeof(struct List));
  124.  
  125.     for ( i = 0; i < TotalNumberOfFiles ; i++ )
  126.     {
  127. /************************************************************
  128.     Step 6:
  129.     Get the length of a filename by telling DragQueryFile
  130.     which file your querying about ( i ), and passing NULL
  131.     for the buffer parameter.
  132. *************************************************************/
  133.         nFileLength  = DragQueryFile( hDrop , i , NULL, 0 );
  134.         pszFileName = (char*)malloc(nFileLength + 1);
  135.  
  136. /************************************************************
  137.     Step 7:
  138.     Copy a file name.   Tell DragQueryFile the file
  139.     your interested in (i) and the length of your buffer.
  140.     NOTE: Make sure that the length is 1 more then the filename
  141.     to make room for the null charater!
  142. *************************************************************/
  143.         DragQueryFile( hDrop , i, pszFileName, nFileLength + 1 );
  144.             //copies over the filename
  145.  
  146.  
  147. /**************************************************************
  148.     Step 8:
  149.     Getting the file dropped. The location is relative to your
  150.     client coordinates, and will have negative values if dropped
  151.     in the non client parts of the window.
  152.  
  153.     DragQueryPoint copies that point where the file was dropped
  154.     and returns whether or not the point is in the client area.
  155.     Regardless of whether or not the file is dropped in the client
  156.     or non-client area of the window, you will still receive the
  157.     file name.
  158. ***************************************************************/
  159.  
  160.         inClientArea = DragQueryPoint( hDrop , &pPoint );
  161.         FLptr= (struct FileList*)malloc(sizeof(struct FileList));
  162.         if(FLHead == NULL)
  163.             FLHead = FLptr;
  164.  
  165.         FileDrop(FLptr, pszFileName , pPoint.x, pPoint.y , inClientArea );
  166.  
  167.         // Add new struct to FileList structure list
  168.         if(FLHead != FLptr)
  169.         {
  170.             FLCurrent->Next=FLptr;
  171.             FLCurrent=FLptr;
  172.             FLptr->Next=NULL;
  173.         }
  174.         else
  175.         {
  176.             FLHead->Next=NULL;
  177.             FLCurrent = FLHead;
  178.         }
  179.     }
  180.     liFiles->FLptr=FLHead;    // Point to first FileList struct in list
  181.     AddFiles( hWnd, (struct List*)liFiles );  //Add this sublist of dropped files
  182.                             //to the big list.
  183. /************************************************************
  184.     Step 9:
  185.     Release the memory shell allocated for this handle
  186.     with DragFinish.
  187.     NOTE: This is a real easy step to forget and could
  188.     explain memory leaks and incorrect program performance.
  189. *************************************************************/
  190.     DragFinish( hDrop );
  191. }
  192.  
  193. /************************************************************/
  194. void AddFiles( HWND hWnd, struct List *pliFiles )
  195. {
  196.     if(liAllFiles==NULL)
  197.     {
  198.         liAllFiles=pliFiles;
  199.         liAllFiles->Next=NULL;
  200.     }
  201.     else
  202.     {
  203.         pliFiles->Next=liAllFiles;  // Put at front of list
  204.         liAllFiles=pliFiles;
  205.     }
  206.     InvalidateRect( hWnd, NULL, TRUE );
  207.     UpdateWindow( hWnd );
  208. }
  209.  
  210. /************************************************************
  211.     Delete FileList structures on linked list
  212. *************************************************************/
  213. void deleteFileList( struct FileList *pFList)
  214. {
  215.     if(pFList->Next != NULL)
  216.         deleteFileList(pFList->Next);   // Recursion - delete next FileList struct
  217.     free(pFList->lpFileName);       // free string allocation
  218.     free(pFList);                   // free structure FileList
  219. }
  220.  
  221. /************************************************************
  222.     Delete List structures on linked list
  223. *************************************************************/
  224. void deleteList( struct List *pliFiles)
  225. {
  226.     if(pliFiles != NULL)
  227.     {
  228.         if(pliFiles->Next != NULL)
  229.             deleteList(pliFiles->Next);     // Recursion - delete next List struct
  230.         if(pliFiles->FLptr != NULL)
  231.             deleteFileList(pliFiles->FLptr);// Initial call to free FileList
  232.         free(pliFiles);             // free List struct
  233.     }
  234. }
  235.  
  236.  
  237. /**********************************************************************/
  238. BOOL InitApplication(HINSTANCE hInstance)
  239. {
  240.     WNDCLASS  wc;
  241.  
  242.     // Fill in window class structure with parameters that describe the
  243.     // main window.
  244.  
  245.     wc.style = CS_HREDRAW | CS_VREDRAW;    // Class style(s).
  246.     wc.lpfnWndProc = (long (FAR PASCAL*)())MainWndProc;    // Function to retrieve messages for
  247.                                                         // windows of this class.
  248.     wc.cbClsExtra = 0;    // No per-class extra data.
  249.     wc.cbWndExtra = 0;    // No per-window extra data.
  250.     wc.hInstance = hInstance;    // Application that owns the class.
  251.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  252.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  253.     wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  254.     wc.lpszMenuName = "DRAGDROPMENU";
  255.     wc.lpszClassName = "DragnDrop"; // Name used in call to CreateWindow.
  256.  
  257.     /* Register the window class and return success/failure code. */
  258.  
  259.     return (RegisterClass(&wc));
  260. }
  261.  
  262.  
  263. /************************************************************************/
  264. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  265. {
  266.     HWND    hWnd;    // Main window handle.
  267.  
  268.     /* Save the instance handle in static variable, which will be used in  */
  269.     /* many subsequence calls from this application to Windows.            */
  270.  
  271.     hInst = hInstance;
  272.  
  273.     /* Create a main window for this application instance.  */
  274.  
  275.     hWnd = CreateWindow(
  276.         "DragnDrop",    // See RegisterClass() call.
  277.         "Drag & Drop Example",    // Text for window title bar.
  278.         WS_OVERLAPPEDWINDOW,    // Window style.
  279.         CW_USEDEFAULT,            // Default horizontal position.
  280.         CW_USEDEFAULT,            // Default vertical position.
  281.         CW_USEDEFAULT,            // Default width.
  282.         CW_USEDEFAULT,            // Default height.
  283.         NULL,                // Overlapped windows have no parent.
  284.         NULL,                // Use the window class menu.
  285.         hInstance,            // This instance owns this window.
  286.         NULL                // Pointer not needed.
  287.     );
  288.  
  289.     /* If window could not be created, return "failure" */
  290.  
  291.     if (!hWnd)
  292.         return (FALSE);
  293.  
  294.     /* Make the window visible; update its client area; and return "success" */
  295.  
  296.     ShowWindow(hWnd, nCmdShow);    // Show the window
  297.     UpdateWindow(hWnd);        // Sends WM_PAINT message
  298.     return (TRUE);        // Returns the value from PostQuitMessage
  299.  
  300. }
  301.  
  302.  
  303. /****************************************************************************
  304.     FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  305. ****************************************************************************/
  306. long FAR PASCAL _export MainWndProc(HWND hWnd, unsigned message,
  307.                      WORD wParam, LONG lParam)
  308. {
  309.     HDC hdc;        // HDC for Window
  310.     PAINTSTRUCT ps;    // Paint Struct for BeginPaint call
  311.     RECT rect;
  312.     struct List* Ltemp;
  313.     struct FileList* FLtemp;
  314.     char *bufstring;
  315.     int i;
  316.  
  317.     switch (message) {
  318.     case WM_CREATE:    // Initialize Global vars
  319.             GetHelp=TRUE;
  320. /************************************************************
  321.     liAllFiles is a pointer to a linked list of structure
  322.     List.  Each List in the linked list will contain the file
  323.     names that were received during a WM_DROPFILES messages
  324.     and will be stored in a linked list of structure FileList.
  325. *************************************************************/
  326.             liAllFiles=NULL;
  327.  
  328. /****************************************************************
  329.     Step 1:
  330.     calling DragAcceptFiles.  If you pass FALSE, you're saying
  331.     I don't accept them anymore.
  332. *****************************************************************/
  333.             DragAcceptFiles( hWnd , TRUE );
  334.  
  335.         return NULL;
  336.     case WM_DROPFILES:
  337. /************************************************************
  338.     Step 2:
  339.     Make call to WMDropFiles
  340. *************************************************************/
  341.             WMDropFiles(wParam, hWnd);
  342.         break;
  343.     case WM_PAINT:
  344.     // Display the file name(s)
  345.             hdc=BeginPaint(hWnd,&ps);
  346.             if(GetHelp)
  347.             {
  348.                 GetClientRect(hWnd,&rect);
  349.                 DrawText(hdc,HelpText,strlen(HelpText),&rect,DT_CENTER|DT_WORDBREAK);
  350.             }
  351.             else
  352.             {
  353.                 SetBkMode ( hdc , TRANSPARENT );
  354.                 Ltemp=liAllFiles;
  355.  
  356.                 i=0;
  357.                 while ( Ltemp != NULL )
  358.                 {
  359.                     FLtemp=Ltemp->FLptr;
  360.                     while( FLtemp != NULL )
  361.                     {
  362.                         bufstring = WhoAmI(FLtemp);
  363.                         TextOut( hdc, 10, 20 * i++, bufstring, strlen(bufstring));
  364.                         FLtemp=FLtemp->Next;
  365.                     }
  366.                     i++;
  367.                     Ltemp=Ltemp->Next;
  368.                 }
  369.             }
  370.             EndPaint(hWnd,&ps);
  371.         break;
  372.     case WM_COMMAND:    // message: command from application menu
  373.         switch(wParam)
  374.         {
  375.             case 101:
  376.                 GetHelp=TRUE;
  377.                 InvalidateRect(hWnd,NULL,TRUE);
  378.                 UpdateWindow(hWnd);
  379.             break;
  380.             case 102:
  381.                 GetHelp=FALSE;
  382.                 InvalidateRect(hWnd,NULL,TRUE);
  383.                 UpdateWindow(hWnd);
  384.             break;
  385.             case 103:
  386.                 GetHelp=FALSE;
  387.                 deleteList(liAllFiles);
  388.                 liAllFiles=NULL;
  389.                 InvalidateRect(hWnd,NULL,TRUE);
  390.                 UpdateWindow(hWnd);
  391.             break;
  392.             case 104:
  393.                 MessageBox(hWnd,"DRAG n' DROP Example\nCopyright (c) 1992 Borland International, Inc.","ABOUT BOX",MB_OK);
  394.             break;
  395.  
  396.             default:
  397.             break;
  398.         }
  399.         break;
  400.     case WM_CLOSE:
  401. /****************************************************************
  402.     Step 10:
  403.     Don't accept files anymore
  404. *****************************************************************/
  405.             DragAcceptFiles( hWnd , FALSE );
  406.  
  407.             deleteList(liAllFiles);
  408.             DestroyWindow(hWnd);
  409.         break;
  410.     case WM_QUIT:
  411.     case WM_DESTROY:    // message: window being destroyed
  412.             PostQuitMessage(0);
  413.         break;
  414.     default:            // Passes it on if unproccessed
  415.         return (DefWindowProc(hWnd, message, wParam, lParam));
  416.     }
  417.     return (NULL);
  418. }
  419.  
  420. #pragma argsused
  421. /**************************************************************/
  422. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  423.              LPSTR lpCmdLine, int nCmdShow)
  424. {
  425.     MSG msg;        // message
  426.     if (!hPrevInstance)    // Other instances of app running?
  427.     if (!InitApplication(hInstance))    // Initialize shared things
  428.         return (FALSE);    // Exits if unable to initialize
  429.  
  430.     /* Perform initializations that apply to a specific instance */
  431.  
  432.     if (!InitInstance(hInstance, nCmdShow))
  433.         return (FALSE);
  434.  
  435.     /* Acquire and dispatch messages until a WM_QUIT message is received. */
  436.  
  437.     while (GetMessage(&msg,    // message structure
  438.         NULL,    // handle of window receiving the message
  439.         NULL,    // lowest message to examine
  440.         NULL))    // highest message to examine
  441.     {
  442.         TranslateMessage(&msg);    // Translates virtual key codes
  443.         DispatchMessage(&msg);    // Dispatches message to window
  444.     }
  445.     return (msg.wParam);    // Returns the value from PostQuitMessage
  446. }
  447.  
  448. // end of file dragdrop.c
  449.