home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Graphics
/
Graphics.zip
/
gall231.zip
/
DDE.ZIP
/
CLIENT.C
< prev
next >
Wrap
Text File
|
1996-04-02
|
18KB
|
591 lines
#pragma title ("Galleria DDE client sample")
#pragma subtitle ("Copyright (c) 1994 Bitware Australia Pty. Ltd.")
//
//
// Galleria DDE client sample
//
// Version 1.0
//
//
// Galleria currently supports the following DDE transactions:
//
// FILE Specifies the full path name of an existing file on disk
// that Galleria is to read and display. The file can be in any
// format currently supported by Galleria.
//
// BITMAP Specifies an in-storage bitmap in OS/2 2.x bitmap format.
// The data sent includes a completed BITMAPINFO2 structure
// (plus RGB2 entries) followed by the image data itself.
//
// ZOOM Specifies a ZOOMDATA structure completed with scaling factor
// and zoom coordinates. Galleria will display its zoom window
// (if not already displayed) then update the contents.
//
// See the comments in the source below for a description of how the DDE
// session is established/terminated and format of the above transactions.
//
// For a more complete description of the DDE interface refer to:
//
// OS/2 2.0 Technical Library: Programming Guide Volume II (Chapter 32)
//
//
// This DDE client requires Galleria Version 2.05 (or later).
//
//
// Copyright (c) 1994
//
// Bitware Australia Pty. Ltd.
// P.O. Box 3097
// Manuka A.C.T. 2603
// Australia
//
// Fax: +61-6-2810175
// CompuServe: 100033,340
// Internet: bitware@ibm.net
//
//
#define INCL_DOS
#define INCL_WIN
#define INCL_GPI
#include <os2.h>
#include <stdlib.h>
#include <string.h>
#include "client.h"
MRESULT EXPENTRY MainProc (HWND, ULONG, MPARAM, MPARAM);
//
// These are the Server and Topic names you need to use for the
// WinDdeInitiate call.
//
// Note that Galleria will *not* enumerate the available topics when
// a WinDdeInitiate request is issued with a null topic.
//
static CHAR szServer [] = "GALLERIA";
static CHAR szTopic [] = "PRIVATE";
//
// This is the format of the data for a ZOOM request. It is appended to the
// DDESTRUCT and pointed to by offabData.
//
typedef struct
{
ULONG ulFactor; // Scaling factor 1-9
USHORT xCoord, yCoord; // x and y coordinates for the
// ZOOM request. (0,0) is bottom
// left. The units are relative pixel
// values in the unscaled image.
} ZOOMDATA, *PZOOMDATA;
INT main
(
ULONG argc, // command line argument count
CHAR *argv [] // command line argument addresses
)
{
HAB hab;
HMQ hmq;
QMSG qmsg;
HWND hwndMain;
// Initialize the application and create message queue
hab = WinInitialize (0);
hmq = WinCreateMsgQueue (hab, 0);
// Create main window
hwndMain = WinLoadDlg (HWND_DESKTOP, HWND_DESKTOP, MainProc,
(HMODULE) NULL, IDD_MAINBOX, NULL);
// Message loop processing
while ( WinGetMsg (hab, &qmsg, (HWND) NULL, 0, 0) )
WinDispatchMsg (hab, &qmsg);
// Destroy main window
WinDestroyWindow (hwndMain);
// Destroy message queue and terminate application
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
return 0;
}
MRESULT EXPENTRY MainProc
(
HWND hwnd, // window handle
ULONG msg, // message
MPARAM mp1, // message parameter 1
MPARAM mp2 // message parameter 2
)
{
//
// You need to store the hwnd for the DDE server somewhere. This program
// puts it into the instance of "Window words" for the window but you
// could also use a static.
//
struct WINDATA
{
HWND hwndDDE;
} *pw;
pw = WinQueryWindowPtr (hwnd, 0);
switch ( msg )
{
//
// Initialize variables and dialog elements.
//
case WM_INITDLG:
{
CHAR szFileName [CCHMAXPATH];
// Allocate area for window static and set pointer
pw = malloc (sizeof (struct WINDATA));
WinSetWindowPtr (hwnd, 0, pw);
// Initialize variables
pw->hwndDDE = (HWND) NULL;
// Fill initial dialog values
DosQueryPathInfo ("CLIENT.BMP", FIL_QUERYFULLNAME, szFileName,
sizeof szFileName);
WinSetDlgItemText (hwnd, IDD_FILENAME, szFileName);
WinSendDlgItemMsg (hwnd, IDD_ZOOMFACTOR, SPBM_SETLIMITS,
MPFROMSHORT (9), MPFROMSHORT (1));
WinSendDlgItemMsg (hwnd, IDD_ZOOMFACTOR, SPBM_SETCURRENTVALUE,
MPFROMSHORT (4), NULL);
WinSetDlgItemShort (hwnd, IDD_ZOOMX, 100, FALSE);
WinSetDlgItemShort (hwnd, IDD_ZOOMY, 100, FALSE);
return 0;
}
//
// WM_DDE_INITIATEACK is received as a response from the
// WinDdeInitiate call. The logic saves the hwnd for the server in
// hwndDDE.
//
// If we get multiple responses (i.e. hwndDDE is already set)
// then we post a WM_DDE_TERMINATE to the others.
//
case WM_DDE_INITIATEACK:
{
PDDEINIT pddei;
COLOR clr;
pddei = PVOIDFROMMP (mp2);
if ( pw->hwndDDE == (HWND) NULL )
{
pw->hwndDDE = (HWND) mp1;
WinSetDlgItemText (hwnd, IDD_STATUS, "Active");
WinSetDlgItemText (hwnd, IDD_ACTIVATE, "Break");
clr = CLR_RED;
WinSetPresParam (WinWindowFromID (hwnd, IDD_ACTIVATE),
PP_FOREGROUNDCOLORINDEX, 4, (PVOID) &clr);
WinEnableControl (hwnd, IDD_SENDFILE, TRUE);
WinEnableControl (hwnd, IDD_SENDBITMAP, TRUE);
WinEnableControl (hwnd, IDD_SENDZOOM, TRUE);
}
else
WinDdePostMsg ((HWND) mp1, hwnd, WM_DDE_TERMINATE,
(PDDESTRUCT) NULL, DDEPM_RETRY);
DosFreeMem (pddei);
return 0;
}
//
// WM_DDE_ACK is received as a response from our WM_DDE_POKE
// request.
//
// Your logic may want to retry on busy conditions. Note that
// a DDE_FBUSY will be received when the server is active processing
// the last request or the user has initiated some activity.
//
case WM_DDE_ACK:
{
PDDESTRUCT pdde;
PSZ pszText;
pdde = PVOIDFROMMP (mp2);
if ( pdde->fsStatus & DDE_FACK )
pszText = "OK";
else if ( pdde->fsStatus & DDE_FBUSY )
pszText = "Busy";
else if ( pdde->fsStatus & DDE_NOTPROCESSED )
pszText = "Error";
else
pszText = "Unknown";
WinSetDlgItemText (hwnd, IDD_RETURNCODE, pszText);
DosFreeMem (pdde);
return 0;
}
//
// WM_DDE_TERMINATE is received when the server terminates or breaks
// the connection.
//
// We also need to send this when terminating the client.
//
case WM_DDE_TERMINATE:
{
COLOR clr;
if ( pw->hwndDDE == (HWND) mp1 )
{
pw->hwndDDE = (HWND) NULL;
WinSetDlgItemText (hwnd, IDD_STATUS, "Inactive");
WinSetDlgItemText (hwnd, IDD_ACTIVATE, "Establish");
clr = CLR_GREEN;
WinSetPresParam (WinWindowFromID (hwnd, IDD_ACTIVATE),
PP_FOREGROUNDCOLORINDEX, 4, (PVOID) &clr);
WinEnableControl (hwnd, IDD_SENDFILE, FALSE);
WinEnableControl (hwnd, IDD_SENDBITMAP, FALSE);
WinEnableControl (hwnd, IDD_SENDZOOM, FALSE);
WinDdePostMsg ((HWND) mp1, hwnd, WM_DDE_TERMINATE,
(PDDESTRUCT) NULL, DDEPM_RETRY);
}
return 0;
}
//
// Intercept the Close command from the System Menu and post a
// WM_QUIT to kill the application.
//
case WM_SYSCOMMAND:
{
if ( SHORT1FROMMP (mp1) == SC_CLOSE )
{
// Terminate
WinPostMsg (hwnd, WM_QUIT, NULL, NULL);
WinDismissDlg (hwnd, FALSE);
return 0;
}
break;
}
//
// Command (in our case, pushbutton) processing.
//
case WM_COMMAND:
{
PDDESTRUCT pdde;
CONVCONTEXT cctxt;
FILEDLG fdg;
ULONG cbData, cbImage, cclr;
PZOOMDATA pzoom;
CHAR szFileName [CCHMAXPATH];
PBITMAPINFO2 pbmi2;
PBYTE pbImage;
PBITMAPFILEHEADER2 pbfh2;
switch ( SHORT1FROMMP (mp1) )
{
//
// Here is where the DDE connection is established (or broken).
// The WinDdeInitiate must be called with the server name of
// "GALLERIA" and topic of "PRIVATE" ... all other requests
// will be ignored.
//
// We then need to wait for the WM_DDE_INITIATEACK to find out
// the hwnd of the server.
//
case IDD_ACTIVATE:
if ( pw->hwndDDE == (HWND) NULL )
{
cctxt.cb = sizeof cctxt;
cctxt.fsContext = DDECTXT_CASESENSITIVE;
cctxt.idCountry = 1;
cctxt.usCodepage = 437;
cctxt.usLangID = 0;
cctxt.usSubLangID = 0;
WinDdeInitiate (hwnd, szServer, szTopic, &cctxt);
}
else
WinSendMsg (hwnd, WM_DDE_TERMINATE, MPFROMLONG (pw->hwndDDE),
NULL);
break;
//
// Invoke the File Open dialog to prompt for file name of image.
//
case IDD_CHANGEFILE:
memset (&fdg, 0, sizeof fdg);
fdg.cbSize = sizeof fdg;
fdg.fl = FDS_OPEN_DIALOG | FDS_CENTER;
WinQueryDlgItemText (hwnd, IDD_FILENAME, sizeof fdg.szFullFile,
fdg.szFullFile);
if ( WinFileDlg (HWND_DESKTOP, hwnd, &fdg) &&
(fdg.lReturn == DID_OK) )
WinSetDlgItemText (hwnd, IDD_FILENAME, fdg.szFullFile);
break;
//
// Here is where we do a FILE request.
//
// The format for this is a DDESTRUCT followed by "FILE" (as
// the ItemName) then the actual file name (ASCIIZ string of
// full path as the Data).
//
// A WM_DDE_ACK will be received with return code info.
//
case IDD_SENDFILE:
WinSetDlgItemText (hwnd, IDD_RETURNCODE, "");
WinQueryDlgItemText (hwnd, IDD_FILENAME, sizeof szFileName,
szFileName);
cbData = sizeof (DDESTRUCT) + 8 + strlen (szFileName) + 1;
pdde = (PDDESTRUCT) NULL;
if ( DosAllocSharedMem ((PPVOID) &pdde, NULL, cbData,
PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE |
OBJ_GIVEABLE) == 0 )
{
pdde->cbData = cbData;
pdde->fsStatus = DDE_FACKREQ;
pdde->usFormat = 0;
pdde->offszItemName = sizeof (DDESTRUCT);
pdde->offabData = sizeof (DDESTRUCT) + 8;
strcpy (DDES_PSZITEMNAME (pdde), "FILE");
strcpy (DDES_PABDATA (pdde), szFileName);
WinDdePostMsg (pw->hwndDDE, hwnd, WM_DDE_POKE, pdde,
DDEPM_RETRY);
}
break;
//
// Here is where we do a BITMAP request.
//
// The format for this is a DDESTRUCT followed by "BITMAP" (as
// the ItemName) then the image in memory. The image in memory
// consists of a completed BITMAPINFO2 structure (allowing for
// 256 RGB2 entries) followed by the image data itself. Note that
// the image data must be at offset 0x440 irrespective of the
// number of RGB2 entries. Both the BITMAPINFO2 and image data
// must be in standard OS/2 2.x format (cbSize = 64; cPlanes = 1;
// cBitCount = 1, 4, 8 or 24 ... be sure to initialize all other
// fields correctly).
//
// In this example the image data is obtained by dumping that
// from a bitmap resource but any logic that can create data in
// the above format will do.
//
// A WM_DDE_ACK will be received with return code info.
//
case IDD_SENDBITMAP:
WinSetDlgItemText (hwnd, IDD_RETURNCODE, "");
pbfh2 = (PBITMAPFILEHEADER2) NULL;
DosGetResource ((HMODULE) NULL, RT_BITMAP, IDB_IMAGE,
(PPVOID) &pbfh2);
cbImage = ((pbfh2->bmp2.cx * pbfh2->bmp2.cBitCount + 31) / 32) *
4 * pbfh2->bmp2.cy;
cbData = sizeof (DDESTRUCT) + 8 + sizeof (BITMAPINFOHEADER2) +
256 * sizeof (RGB2) + cbImage;
pdde = (PDDESTRUCT) NULL;
if ( DosAllocSharedMem ((PPVOID) &pdde, NULL, cbData,
PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE |
OBJ_GIVEABLE) == 0 )
{
pdde->cbData = cbData;
pdde->fsStatus = DDE_FACKREQ;
pdde->usFormat = 0;
pdde->offszItemName = sizeof (DDESTRUCT);
pdde->offabData = sizeof (DDESTRUCT) + 8;
strcpy (DDES_PSZITEMNAME (pdde), "BITMAP");
pbmi2 = (PBITMAPINFO2) DDES_PABDATA (pdde);
pbImage = (PBYTE) pbmi2 + sizeof (BITMAPINFOHEADER2) +
256 * sizeof (RGB2);
*(PBITMAPINFOHEADER2) pbmi2 = pbfh2->bmp2;
// Copy RGB2 entries
if ( pbfh2->bmp2.cBitCount <= 8 )
{
cclr = ( pbfh2->bmp2.cclrUsed == 0 ?
1 << pbfh2->bmp2.cBitCount :
pbfh2->bmp2.cclrUsed );
memcpy (pbmi2->argbColor,
(PBYTE) pbfh2 + sizeof (BITMAPFILEHEADER2),
cclr * sizeof (RGB2));
}
memcpy (pbImage, (PBYTE) pbfh2 + pbfh2->offBits, cbImage);
WinDdePostMsg (pw->hwndDDE, hwnd, WM_DDE_POKE, pdde,
DDEPM_RETRY);
}
DosFreeResource (pbfh2);
break;
//
// Here is where we do a ZOOM request.
//
// The format for this is a DDESTRUCT followed by "ZOOM" (as
// the ItemName) then a completed ZOOMDATA structure (as the
// Data). The ZOOMDATA contains the zoom factor and coordinates.
//
// A WM_DDE_ACK will be received with return code info.
//
case IDD_SENDZOOM:
WinSetDlgItemText (hwnd, IDD_RETURNCODE, "");
cbData = sizeof (DDESTRUCT) + 8 + sizeof (ZOOMDATA);
pdde = (PDDESTRUCT) NULL;
if ( DosAllocSharedMem ((PPVOID) &pdde, NULL, cbData,
PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE |
OBJ_GIVEABLE) == 0 )
{
pdde->cbData = cbData;
pdde->fsStatus = DDE_FACKREQ;
pdde->usFormat = 0;
pdde->offszItemName = sizeof (DDESTRUCT);
pdde->offabData = sizeof (DDESTRUCT) + 8;
strcpy (DDES_PSZITEMNAME (pdde), "ZOOM");
pzoom = (PZOOMDATA) DDES_PABDATA (pdde);
WinSendDlgItemMsg (hwnd, IDD_ZOOMFACTOR, SPBM_QUERYVALUE,
MPFROMP (&pzoom->ulFactor), MPFROM2SHORT (0, 0));
WinQueryDlgItemShort (hwnd, IDD_ZOOMX,
(PSHORT) &pzoom->xCoord, FALSE);
WinQueryDlgItemShort (hwnd, IDD_ZOOMY,
(PSHORT) &pzoom->yCoord, FALSE);
WinDdePostMsg (pw->hwndDDE, hwnd, WM_DDE_POKE, pdde,
DDEPM_RETRY);
}
break;
}
return 0;
}
//
// On termination we must send a WM_DDE_TERMINATE to the server. This
// could also be done in WM_CLOSE but WM_DESTROY is safer.
//
case WM_DESTROY:
{
// Kill DDE connection if still active
if ( pw->hwndDDE != (HWND) NULL )
WinDdePostMsg (pw->hwndDDE, hwnd, WM_DDE_TERMINATE,
(PDDESTRUCT) NULL, DDEPM_RETRY);
// Release area for window data
free (pw);
break;
}
}
// Default dialog processing
return ( WinDefDlgProc (hwnd, msg, mp1, mp2) );
}