Ŀ
 SOURCE.C


/***********************************************************************/
/*  SOURCE.C - Drag source program                                     */
/*                                                                     */
/*  This program displays a list of files in the current directory.    */
/*  Drag any file name to EPM, and drop, and the file will be          */
/*  displayed in the editor.                                           */
/***********************************************************************/
#define INCL_WIN
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS

#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define Main main

#define MAX_FILES    1000
#define MY_STARTDRAG (WM_USER + 100)
#define MY_LOAD_LIST (WM_USER + 110)

/***********************************************************************/
/*  Global variables.                                                  */
/***********************************************************************/
HAB      hab = NULLHANDLE;
CHAR     szFormats[] = "<DRM_OS2FILE, DRF_UNKNOWN>";
CHAR     szFileNames[MAX_FILES][CCHMAXPATH] = {0};
HWND     hFrameWnd = NULLHANDLE;
HWND     hListWnd = NULLHANDLE;
PFNWP    SysWndProc = NULL;
PFNWP    ListWndProc = NULL;

/***********************************************************************/
/*  Function prototypes.                                               */
/***********************************************************************/
MRESULT EXPENTRY LocalWndProc (HWND, ULONG, MPARAM, MPARAM);
MRESULT EXPENTRY LocalListProc (HWND, ULONG, MPARAM, MPARAM);
VOID DoDrag ();
VOID LoadList ();

/***********************************************************************/
/*   Main() - program entry point.                                     */
/***********************************************************************/
Main ()
{
  HMQ          hmq = NULLHANDLE;
  QMSG         qmsg = {0};
  FRAMECDATA   fcd = {0};

  if (!(hab = WinInitialize (0))) return 0;
  if (!(hmq = WinCreateMsgQueue (hab, 0))) return 0;

/***********************************************************************/
/*  Setup the frame control data for the frame window.                 */
/***********************************************************************/
  memset (&fcd, 0, sizeof (fcd));
  fcd.cb = sizeof (FRAMECDATA);
  fcd.flCreateFlags = FCF_TITLEBAR        |
                      FCF_SYSMENU         |
                      FCF_SIZEBORDER      |
                      FCF_SHELLPOSITION   |
                      FCF_MINMAX          |
                      FCF_TASKLIST;

/***********************************************************************/
/*  Create the frame - it will hold the list box.                      */
/***********************************************************************/
  hFrameWnd = WinCreateWindow (HWND_DESKTOP,
                               WC_FRAME,
                               "Drag Source",
                               0, 0, 0, 0, 0,
                               NULLHANDLE,
                               HWND_TOP,
                               0,
                               &fcd,
                               NULL);

  if (!hFrameWnd) return 0;

/***********************************************************************/
/*  Set an icon for the frame window.                                  */
/***********************************************************************/
  WinSendMsg (hFrameWnd,
              WM_SETICON,
              (MPARAM) WinQuerySysPointer (HWND_DESKTOP,
                                           SPTR_PROGRAM,
                                           0),
              NULL);

/***********************************************************************/
/*  Create a list window child - we will list files in it.             */
/***********************************************************************/
  hListWnd = WinCreateWindow (hFrameWnd,
                              WC_LISTBOX,
                              NULL,
                              0, 0, 0, 0, 0,
                              hFrameWnd,
                              HWND_BOTTOM,
                              FID_CLIENT,
                              NULL,
                              NULL);

/***********************************************************************/
/*  We must intercept the frame window's messages.                     */
/*  We save the return value (the current WndProc),                    */
/*  so we can pass it all the other messages the frame gets.           */
/***********************************************************************/
  SysWndProc  = WinSubclassWindow (hFrameWnd, (PFNWP) LocalWndProc);
  ListWndProc = WinSubclassWindow (hListWnd, (PFNWP) LocalListProc);

  WinShowWindow (hFrameWnd, 1);
  WinPostMsg (hFrameWnd, MY_LOAD_LIST, 0, 0);

/***********************************************************************/
/*  Standard PM message loop - get it, dispatch it.                    */
/***********************************************************************/
  while (WinGetMsg (hab, &qmsg, NULLHANDLE, 0, 0))
    WinDispatchMsg (hab, &qmsg);

/***********************************************************************/
/*  Clean up on the way out.                                           */
/***********************************************************************/
  WinDestroyWindow (hFrameWnd);
  WinDestroyMsgQueue (hmq);
  WinTerminate (hab);

  return 0;
}

/***********************************************************************/
/*  LocalWndProc() - intercepts frame window messages.                 */
/***********************************************************************/
MRESULT EXPENTRY LocalWndProc (HWND hwnd, ULONG msg, 
                                          MPARAM mp1, MPARAM mp2)
{
  switch (msg)
  {
    case MY_LOAD_LIST:
      LoadList ();
    return 0;

    case MY_STARTDRAG:
      DoDrag ();
    return 0;

    default:
    return (*SysWndProc) (hwnd, msg, mp1, mp2);
  }

  return 0;
}

/***********************************************************************/
/*  LocalListProc() - List box subclassing                             */
/*  (all we care about is starting a drag).                            */
/***********************************************************************/
MRESULT EXPENTRY LocalListProc (HWND hwnd, ULONG msg, 
                                           MPARAM mp1, MPARAM mp2)
{
  if (msg == WM_BEGINDRAG)
  {
    WinPostMsg (hFrameWnd, MY_STARTDRAG, 0, 0);
  }
  else
  {
    return (*ListWndProc) (hwnd, msg, mp1, mp2);
  }

  return 0;
}

/***********************************************************************/
/*  DoDrag() - the actual drag function.                               */
/***********************************************************************/
VOID DoDrag ()
{
  CHAR             szBuffer[CCHMAXPATH] = "";
  LONG             index = 0;
  LONG             len = 0;
  HWND             hTargetWnd = NULLHANDLE;
  LHANDLE          hImage = NULLHANDLE;
  ULONG            curdrive = 0;
  ULONG            drivemap = 0;
  CHAR             szContainer[CCHMAXPATH] = "";
  PDRAGINFO        pDraginfo = NULL;
  ULONG            quantity = 0;
  DRAGITEM         Dragitem = {0};
  DRAGIMAGE        dimg = {0};
  ULONG            dirlen = 0;

/***********************************************************************/
/*  Get the file name from the listbox.                                */
/***********************************************************************/
  index = (LONG) WinSendMsg (hListWnd, LM_QUERYSELECTION, 
                                       MPFROMLONG (LIT_FIRST), NULL);
  if (index == LIT_NONE) return;

  len = (LONG) WinSendMsg (hListWnd, LM_QUERYITEMTEXTLENGTH, 
                                     MPFROMSHORT (index), NULL);

  WinSendMsg (hListWnd, LM_QUERYITEMTEXT, 
                        MPFROM2SHORT (index, len), MPFROMP (szBuffer));

/***********************************************************************/
/*  Allocate the DRAGINFO data structure for one DRAGITEM structure.   */
/*  NB: No memset() function here.                                     */
/***********************************************************************/
  quantity = 1;
  pDraginfo = DrgAllocDraginfo (quantity);
  if (!pDraginfo) return;

/***********************************************************************/
/*  Set info, prepare for drag.                                        */
/***********************************************************************/
  DosQueryCurrentDisk (&curdrive, &drivemap);
  szContainer[0] = (CHAR) curdrive + 64;
  szContainer[1] = ':';
  szContainer[2] = '\\';
  dirlen = CCHMAXPATH - 1;
  DosQueryCurrentDir (0, &szContainer[3], &dirlen);
  strcat (szContainer, "\\");

  Dragitem.hwndItem          = hListWnd;
  Dragitem.ulItemID          = index;
  Dragitem.hstrRMF           = DrgAddStrHandle (szFormats);

  Dragitem.hstrContainerName = DrgAddStrHandle (szContainer);
  Dragitem.hstrSourceName    = DrgAddStrHandle (szBuffer);

  Dragitem.fsSupportedOps    = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE;

  DrgSetDragitem (pDraginfo,
                  &Dragitem,
                  sizeof (DRAGITEM),
                  0);

/***********************************************************************/
/*  Initialize the drag image.                                         */
/***********************************************************************/
  dimg.cb       = sizeof (DRAGIMAGE);
  dimg.hImage   = WinQuerySysPointer (HWND_DESKTOP, SPTR_FILE, 0);
  dimg.fl       = DRG_ICON;

/***********************************************************************/
/*  Perform drag operation.                                            */
/***********************************************************************/
  DrgDrag (hFrameWnd,
           pDraginfo,
           &dimg,
           quantity,
           VK_ENDDRAG,
           NULL);

/***********************************************************************/
/*  Free memory.                                                       */
/***********************************************************************/
  DrgFreeDraginfo (pDraginfo), pDraginfo = NULL;
}

/***********************************************************************/
/*  Load list.                                                         */
/***********************************************************************/
VOID LoadList ()
{
  FILEFINDBUF3  ffbFile = {0};
  HDIR          hDir = NULLHANDLE;
  ULONG         rc = 0;
  ULONG         x = 0;
  ULONG         dirlen = 0;
  ULONG         cntr = 0;

/***********************************************************************/
/*  We use a DosFindFirst()/DosFindNext() loop to fill the list box.   */
/***********************************************************************/
  hDir  = HDIR_CREATE;
  cntr = 1;
  rc = DosFindFirst ("*",
                     &hDir,
                     0,
                     &ffbFile,
                     sizeof (FILEFINDBUF3),
                     &cntr,
                     FIL_STANDARD);

  x = 0;
  do
  {
    sprintf (szFileNames[x], "%s", ffbFile.achName);
    WinSendMsg (hListWnd, LM_INSERTITEM, 
                          MPFROMSHORT (LIT_END), szFileNames[x]);

    cntr = 1; x ++;
    rc = DosFindNext (hDir,
                      &ffbFile,
                      sizeof (FILEFINDBUF3),
                      &cntr);
  }
  while (cntr && (rc == NO_ERROR) && (x < MAX_FILES));

  DosFindClose (hDir);
}

Ŀ
 SOURCE.DEF


NAME DND-SOURCE-V1
WINDOWAPI

Ŀ
 TARGET.C


/***********************************************************************/
/*  TARGET.C - Drag target program                                     */
/***********************************************************************/
#define  INCL_WIN
#define  INCL_GPI

#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define Main main

#define MAX_ITEMS 1000
#define MY_ACCEPT_OBJECTS (WM_USER + 100)

/***********************************************************************/
/*  Global variables.                                                  */
/***********************************************************************/
HAB     hab = NULLHANDLE;
HWND    hFrameWnd = NULLHANDLE;
PFNWP   SysWndProc = NULL;

/***********************************************************************/
/*  Function prototypes.                                               */
/***********************************************************************/
MRESULT EXPENTRY LocalWndProc (HWND, ULONG, MPARAM, MPARAM);
VOID DrawEmphasisRectangle (HWND, ULONG);

/***********************************************************************/
/*  Main() - program entry point.                                      */
/***********************************************************************/
Main ()
{
  HMQ         hmq = NULLHANDLE;
  QMSG        qmsg = {0};
  FRAMECDATA  fcd = {0};

  if (!(hab = WinInitialize (0))) return 0;
  if (!(hmq = WinCreateMsgQueue (hab, 0))) return 0;

/***********************************************************************/
/*  Set up the frame control data for the frame window.                */
/***********************************************************************/
  fcd.cb = sizeof (FRAMECDATA);
  fcd.flCreateFlags = FCF_TITLEBAR      |
                      FCF_SYSMENU       |
                      FCF_SIZEBORDER    |
                      FCF_SHELLPOSITION |
                      FCF_MINMAX        |
                      FCF_TASKLIST;

/***********************************************************************/
/*  Create the frame window.                                           */
/***********************************************************************/
  hFrameWnd = WinCreateWindow (HWND_DESKTOP,
                               WC_FRAME,
                               "Drag Target",
                               0,
                               0, 0, 0, 0,
                               NULLHANDLE,
                               HWND_TOP,
                               0,
                               &fcd,
                               NULL);

  if (!hFrameWnd) return 0;

/***********************************************************************/
/*  Set an icon for the frame window.                                  */
/***********************************************************************/
  WinSendMsg (hFrameWnd,
              WM_SETICON,
              (MPARAM) WinQuerySysPointer (HWND_DESKTOP,
                                           SPTR_PROGRAM,
                                           0),
              NULL);

/***********************************************************************/
/*  We must intercept the frame window's messages                      */
/*  (to capture any input from the container control).                 */
/*  We save the return value (the current WndProc),                    */
/*  so we can pass it all the other messages the frame gets.           */
/***********************************************************************/
  SysWndProc = WinSubclassWindow (hFrameWnd, (PFNWP) LocalWndProc);

  WinShowWindow (hFrameWnd, 1);

/***********************************************************************/
/*  Standard PM message loop - get it, dispatch it.                    */
/***********************************************************************/
  while (WinGetMsg (hab, &qmsg, NULLHANDLE, 0, 0))
    WinDispatchMsg (hab, &qmsg);

/***********************************************************************/
/*  Clean up on the way out.                                           */
/***********************************************************************/
  WinDestroyWindow (hFrameWnd);
  WinDestroyMsgQueue (hmq);
  WinTerminate (hab);

  return 0;
}

/***********************************************************************/
/*  LocalWndProc() - window procedure for the frame window.            */
/*  Called by PM whenever a message is sent to the frame.              */
/***********************************************************************/
MRESULT EXPENTRY LocalWndProc (HWND hwnd, ULONG msg, 
                                          MPARAM mp1, MPARAM mp2)
{
  CHAR        szDir[CCHMAXPATH] = "";
  CHAR        szBuffer[CCHMAXPATH] = "";
  PDRAGINFO   dragInfo = NULL;
  PDRAGITEM   dragItem = NULL;
  USHORT      usOp = 0;
  USHORT      usIndicator = 0;
  USHORT      cItems = 0;
  USHORT      i = 0;
  ULONG       ulBytes = 0;

  switch (msg)
  {
/***********************************************************************/
/*  Someone's dragging something over us.                              */
/***********************************************************************/
    case DM_DRAGOVER:
      /* Draw rectangle */
      DrawEmphasisRectangle (hwnd, 1);

      /* Get access to the DRAGINFO data structure */
      dragInfo = (PDRAGINFO) mp1;
      if (!DrgAccessDraginfo (dragInfo)) 
        return MRFROM2SHORT (DOR_NODROP, 0);

      /* Check operation */
      usOp = dragInfo->usOperation;

      switch (usOp)
      {
        case DO_DEFAULT:
          usOp = DO_MOVE;
        break;

        case DO_COPY:
        case DO_MOVE:
        case DO_LINK:
        break;

        case DO_CREATE:
        case DO_UNKNOWN:
        default:
          DrgFreeDraginfo (dragInfo);
          return MRFROM2SHORT (DOR_NODROP, 0);
        break;
      }

      /* Enumerate and check objects */
      usIndicator = DOR_DROP;

      cItems = DrgQueryDragitemCount (dragInfo);
      if (!cItems || cItems > MAX_ITEMS)
      {
        DrgFreeDraginfo (dragInfo);
        return MRFROM2SHORT (DOR_NODROP, 0);
      }

      for (i = 0; i < cItems; i ++)
      {
        dragItem = DrgQueryDragitemPtr (dragInfo, i);

        if (!DrgVerifyRMF (dragItem, "DRM_OS2FILE", NULL))
        {
          DrgFreeDraginfo (dragInfo);
          return MRFROM2SHORT (DOR_NODROP, 0);
        }
      }

      /* Release the DRAGINFO data structure */
      DrgFreeDraginfo (dragInfo);

    /* Return */
    return MRFROM2SHORT (usIndicator, usOp);

/***********************************************************************/
/*  Dragged object just left.                                          */
/***********************************************************************/
    case DM_DRAGLEAVE:
      /* Hide rectangle */
      DrawEmphasisRectangle (hwnd, 0);

    /* Return */
    return 0;

/***********************************************************************/
/*  Receive objects.                                                   */
/***********************************************************************/
    case DM_DROP:
      /* Hide rectangle */
      DrawEmphasisRectangle (hwnd, 0);

      /* Move window on top - for WinMessageBox() only */
      WinSetActiveWindow (HWND_DESKTOP, hwnd);

      /* Accept objects */
      WinPostMsg (hwnd,
                  MY_ACCEPT_OBJECTS,
                  mp1,
                  0);

    /* Return */
    return 0;

/***********************************************************************/
/*  Accept objects                                                     */
/***********************************************************************/
    case MY_ACCEPT_OBJECTS:
      /* Get access to the DRAGINFO data structure */
      dragInfo = (PDRAGINFO) mp1;
      if (!DrgAccessDraginfo (dragInfo)) return 0;

      /* Enumerate objects */
      cItems = DrgQueryDragitemCount (dragInfo);

      for (i = 0; i < cItems; i ++)
      {
        dragItem = DrgQueryDragitemPtr (dragInfo, i);

        szDir[0] = szBuffer[0] = 0;

        if (DrgQueryStrNameLen (dragItem->hstrContainerName) < sizeof (szDir))
            DrgQueryStrName (dragItem->hstrContainerName, sizeof (szDir), szDir);

        if (DrgQueryStrNameLen (dragItem->hstrSourceName) < sizeof(szBuffer))
            DrgQueryStrName (dragItem->hstrSourceName, sizeof (szBuffer), szBuffer);

        if (!szDir[0] || !szBuffer[0]) continue;

        if (dragItem->fsControl & DC_OPEN) strcat (szBuffer, " (Read-only)");
        if (dragItem->fsControl & DC_CONTAINER) strcat (szBuffer, " (WPFolder)");

        WinMessageBox (HWND_DESKTOP, NULLHANDLE,
                       szBuffer, "Dropped", 0, 0);

        DrgSendTransferMsg (dragInfo->hwndSource,
                            DM_ENDCONVERSATION,
                            MPFROMLONG (dragItem->ulItemID),
                            MPFROMSHORT (DMFL_TARGETSUCCESSFUL));
      }

      /* Release the DRAGINFO data structure */
      DrgFreeDraginfo (dragInfo);

    /* Return */
    return 0;
  }

  /* Send the message to the usual WC_FRAME WndProc */
  return (*SysWndProc) (hwnd, msg, mp1, mp2);
}

/***********************************************************************/
/*  DrawEmphasisRectangle() - draw CUA'91 emphasis.                    */
/***********************************************************************/
VOID DrawEmphasisRectangle (HWND hwnd, ULONG req)
{
  RECTL       rectangle = {0};
  POINTL      point = {0};
  HPS         hps = NULLHANDLE;

  WinQueryWindowRect (hwnd, &rectangle);

  rectangle.xLeft = rectangle.xLeft +
                    WinQuerySysValue (HWND_DESKTOP, SV_CXSIZEBORDER);

  rectangle.yBottom = rectangle.yBottom +
                      WinQuerySysValue (HWND_DESKTOP, SV_CYSIZEBORDER);

  rectangle.xRight = rectangle.xRight -
                     (WinQuerySysValue (HWND_DESKTOP, SV_CXSIZEBORDER) + 1);

  rectangle.yTop = rectangle.yTop -
                   (WinQuerySysValue (HWND_DESKTOP, SV_CYSIZEBORDER) +
                    WinQuerySysValue (HWND_DESKTOP, SV_CYTITLEBAR) + 1);

  hps = DrgGetPS (hwnd);

  if (req) GpiSetColor (hps, CLR_NEUTRAL);
  else GpiSetColor (hps, CLR_BACKGROUND);

  point.x = rectangle.xLeft;
  point.y = rectangle.yBottom;
  GpiMove (hps, &point);
  point.x = rectangle.xLeft;
  point.y = rectangle.yTop;
  GpiLine (hps, &point);
  point.x = rectangle.xRight;
  point.y = rectangle.yTop;
  GpiLine (hps, &point);
  point.x = rectangle.xRight;
  point.y = rectangle.yBottom;
  GpiLine (hps, &point);
  point.x = rectangle.xLeft;
  point.y = rectangle.yBottom;
  GpiLine (hps, &point);

  point.x = rectangle.xLeft + 1;
  point.y = rectangle.yBottom + 1;
  GpiMove (hps, &point);
  point.x = rectangle.xLeft + 1;
  point.y = rectangle.yTop - 1;
  GpiLine (hps, &point);
  point.x = rectangle.xRight - 1;
  point.y = rectangle.yTop - 1;
  GpiLine (hps, &point);
  point.x = rectangle.xRight - 1;
  point.y = rectangle.yBottom + 1;
  GpiLine (hps, &point);
  point.x = rectangle.xLeft + 1;
  point.y = rectangle.yBottom + 1;
  GpiLine (hps, &point);

  DrgReleasePS (hps);
}

Ŀ
 TARGET.DEF


NAME DND-TARGET-V1
WINDOWAPI