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

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