home *** CD-ROM | disk | FTP | other *** search
- /*
- DDCLIENT.C -- Illustrates 3.0 and 3.1 Drag and Drop protocols
-
- Copyright (c) Dave Maxey 1992
-
- From Chapter 6 of "Undocumented Windows" (Addison-Wesley 1992)
- by Andrew Schulman, Dave Maxey and Matt Pietrek
-
- Build using: WINIOBC DDCLIENT (for Borland C++ v3.00)
- WINIOMS DDCLIENT (for Microsoft C/SDK)
-
- DDCLIENT.C is slightly changed from the way it appears in the book
- because the DRAGOBJ_ constants (from DRAGDROP.H) have been split out.
- The DDCLIENT.C in the text incorrectly assumed that DRAGOBJ_PROGRAM,
- for example, included the DRAGOBJ_EXTERNAL flag.
- */
-
- #include <windows.h>
- #include <string.h>
- #include <dos.h>
- #include "wmhandlr.h"
- #include "winio.h"
- #include "dragdrop.h"
- #ifndef __BORLANDC__
- #define MK_FP(a,b) ((void far *)(((unsigned long)(a) << 16) | (b)))
- #endif
-
- BOOL tInClientArea = FALSE;
-
- // We also get documented drag and drop in 3.1
- // Here we don't use the documented API, but rather manipulate the
- // undocumented DROPINFO structure directly.
- long my_dropfiles(HWND hwnd, WORD wMsg, WORD wParam, DWORD lParam)
- {
- LPDROPINFO lpDropInfo;
- int i = 0;
- LPSTR lpszFile;
-
- printf("WM_DROPFILES received\n");
-
- lpDropInfo = (LPDROPINFO) GlobalLock(wParam);
- lpszFile = (LPSTR) &lpDropInfo->chBuffer;
-
- while (*lpszFile)
- {
- i++;
- printf("%02d File name : %Fs\n", i, lpszFile);
- lpszFile = (LPSTR) ((DWORD) lpszFile + lstrlen(lpszFile) + 1);
- }
-
- GlobalUnlock(wParam);
-
- // Replicates the functionality of DragFinish!
- GlobalFree(wParam);
-
- return 1;
- }
-
- // Handles WM_DROPOBJECT - Sent when user releases left button
- // inside our client area.
- long drop_handler(HWND h, WORD wMsg, WORD wParam, DWORD lParam)
- {
- LPOFSTRUCT lpofstruct;
- LPDRAGINFO lpDragInfo;
- LPSTR lpTail, lpHead, lpFileName;
- WORD wSourceDS;
- int i = 0;
- char szPath[120];
- char *szFile;
- BOOL bPath;
- static const char *szObjType[] = {"executable", "data/text file",
- "directory", "multiple files/dirs"};
-
- // Reset ready for next drag/drop
- tInClientArea = FALSE;
-
- lpDragInfo = (LPDRAGINFO) lParam;
-
- // Get source app (File Manager, presumably) DS
- wSourceDS = (GetWindowWord(lpDragInfo->hwndSource, GWW_HINSTANCE)
- & 0xfffc) | 1;
-
- // Use wFlags field (without top bit, and decremented to
- // zero-base) as index to get object type string.
- printf("Drop in progress...\n"
- "------------------------------\n"
- "Object type : %s\n",
- szObjType[(lpDragInfo->wFlags - 1) & 3]);
-
- // hOfstruct only non-NULL when a single file, and
- // extension has association
- if (lpDragInfo->hOfstruct)
- {
- lpofstruct = (LPOFSTRUCT) MK_FP(lpDragInfo->hOfstruct, 0);
- printf("01 File name : %Fs\n\t(Extension has association)\n"
- "------------------------------\n"
- "Drop completed successfully\n\n",
- lpofstruct->szPathName);
-
- return DRAG_FILE;
- }
-
- // This returns a list of files and complete directory paths
- // by forming a far pointer into the source application's near
- // heap and parsing to space characters. If a list item has no
- // path, we assume that the source app is or emulates FileMan,
- // and use the source window title to obtain the directory.
- // This technique is not only a hack, but it only works in v3.0!
- // In 3.1 we can use the documented API.
-
- if ((GetWindowText(lpDragInfo->hwndSource,
- (LPSTR) szPath, sizeof(szPath))) ||
- (GetWindowText(GetParent(lpDragInfo->hwndSource),
- (LPSTR) szPath, sizeof(szPath))))
- {
- szFile = szPath + strlen(szPath);
- while (szFile && (*szFile != '\\')) szFile--;
- ++szFile;
- }
- else
- szFile = szPath;
-
- lpTail = (LPSTR) MK_FP(wSourceDS, (WORD) (lpDragInfo->szList));
-
- do {
- // Separate out next 'token', record whether it contains a path
- lpHead = lpTail;
- bPath = FALSE;
- while (*lpTail != ' ')
- if (*lpTail++ == '\\')
- bPath = TRUE;
-
- *lpTail = 0;
-
- // if list item has no path, use szPath.
- if (! bPath)
- {
- lstrcpy((LPSTR) szFile, lpHead);
- lpFileName = (LPSTR) &szPath;
- }
- else
- lpFileName = lpHead;
-
- printf("%02d %s : %Fs\n",
- ++i,
- bPath ? "Directory" : "File name",
- lpFileName);
-
- *lpTail++ = ' ';
-
- } while (*lpTail);
-
- printf("-----------------------------\n"
- "Drop completed successfully\n\n");
-
- return DRAG_FILE;
- }
-
-
- // Handles WM_QUERYDROPOBJECT - Sent whenever the object being
- // dragged moves over our window.
- long query_handler(HWND h, WORD w, WORD wParam, DWORD lParam)
- {
- LPDRAGINFO lpDragInfo = (LPDRAGINFO) lParam;
-
- // Dragged icon has reached client area (wParam == 0).
- // Since lParam is a DRAGINFOPTR, we can decide whether we
- // want to accept on the basis of file-type, and whether or
- // not 'associated'. This code is only here to illustrate
- // the point, and is a pointless and redundant test,
- // and accepts all object types.
- if ((wParam == 0) &&
- ((lpDragInfo->wFlags == DRAGOBJ_PROGRAM | DRAGOBJ_EXTERNAL) ||
- (lpDragInfo->wFlags == DRAGOBJ_DATA | DRAGOBJ_EXTERNAL) ||
- (lpDragInfo->wFlags == DRAGOBJ_DIRECTORY | DRAGOBJ_EXTERNAL) ||
- (lpDragInfo->wFlags == DRAGOBJ_MULTIPLE | DRAGOBJ_EXTERNAL) ||
- (lpDragInfo->hOfstruct != NULL)))
- return 1;
- else
- return 0;
- }
-
-
- // Handles WM_DRAGSELECT - Sent whenever the object being
- // dragged moves into or out of our client area. We don't actually
- // need to handle this one.
- long select_handler(HWND h, WORD w1, WORD w2, DWORD l)
- {
- printf("Drag %s\n",
- (tInClientArea ^= 1) ? "in progress" : "suspended");
-
- return 1;
- }
-
- // Handles WM_DRAGMOVE - Sent whenever the object being
- // dragged is dragged after we have signaled acceptance of it.
- // We don't actually need to handle this one, either.
- long move_handler(HWND h, WORD w1, WORD w2, DWORD l)
- {
- return 1;
- }
-
-
- int main()
- {
- winio_settitle(__hMainWnd, "Drag'n'Drop Client");
-
- winio_about("DDCLIENT"
- "\nIllustrates 3.0 and 3.1 Drag and Drop protocols"
- "\n\nFrom Chapter 6 of"
- "\n\"Undocumented Windows\" (Addison-Wesley, 1992)"
- "\nby Andrew Schulman, David Maxey and Matt Pietrek"
- );
-
- wmhandler_set(__hMainWnd, WM_DROPOBJECT,
- (WMHANDLER) drop_handler);
- wmhandler_set(__hMainWnd, WM_QUERYDROPOBJECT,
- (WMHANDLER) query_handler);
- wmhandler_set(__hMainWnd, WM_DRAGSELECT,
- (WMHANDLER) select_handler);
- wmhandler_set(__hMainWnd, WM_DRAGMOVE,
- (WMHANDLER) move_handler);
- wmhandler_set(__hMainWnd, WM_DROPFILES,
- (WMHANDLER) my_dropfiles);
-
- printf(
- "This program lists any files dragged over and\n"
- "dropped on it from the accompanying DDSERVER\n"
- "program, or from File Manager, or any other\n"
- "program that uses the undocumented 3.0 or\n"
- "partially documented 3.1 protocol.\n\n"
- "Waiting for drag'n'drop messages...\n\n");
-
- return 0;
- }
-