home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
On Hand
/
On_Hand_From_Softbank_1994_Release_2_Disc_2_1994.iso
/
00202
/
s
/
disk3
/
pix.c_
/
pix.bin
Wrap
Text File
|
1993-04-28
|
23KB
|
689 lines
//---------------------------------------------------------------------------
// Copyright (C) 1991-93, Microsoft Corporation
//
// You have a royalty-free right to use, modify, reproduce and distribute
// the Sample Custom Control Files (and/or any modified version) in any way
// you find useful, provided that you agree that Microsoft has no warranty,
// obligation or liability for any Custom Control File.
//---------------------------------------------------------------------------
// Pix.c
//---------------------------------------------------------------------------
// Contains control procedure for PIX control
//---------------------------------------------------------------------------
#include <windows.h>
#include <vbapi.h>
#include "pictblt.h"
#include "pix.h"
#include "pixvb1.h"
//---------------------------------------------------------------------------
// Global Variables
//---------------------------------------------------------------------------
HANDLE hmodDLL;
//---------------------------------------------------------------------------
// Standard Error Values
//---------------------------------------------------------------------------
#define ERR_None 0
#define ERR_OutOfMemory 7 // Error$(7) = "Out of memory"
#define ERR_BadIndex 381 // Error$(381) = "Invalid property array index"
#define ERR_BadPixFmt 32000 // User-defined error
//---------------------------------------------------------------------------
// Local Prototypes
//---------------------------------------------------------------------------
ERR ErrCopyHlstr(HLSTR FAR *lphlstrDest, HLSTR hlstrSrc);
VOID NEAR PaintPix(HCTL hctl, HDC hdc, LPRECT lprect);
#define LppixDEREF(hctl) ((PPIX)VBDerefControl(hctl))
//---------------------------------------------------------------------------
// Private macros
//---------------------------------------------------------------------------
#define SETOPAQUE(hctl) VBSetControlFlags(hctl, CTLFLG_GRAPHICALOPAQUE, CTLFLG_GRAPHICALOPAQUE)
#define SETTRANSLUCENT(hctl) VBSetControlFlags(hctl, CTLFLG_GRAPHICALTRANSLUCENT, CTLFLG_GRAPHICALTRANSLUCENT)
#define SETTRANSPARENT(hctl) VBSetControlFlags(hctl, CTLFLG_GRAPHICALOPAQUE|CTLFLG_GRAPHICALTRANSLUCENT, 0)
//---------------------------------------------------------------------------
// Pix Control Procedure
//---------------------------------------------------------------------------
LONG FAR PASCAL _export PixCtlProc
(
HCTL hctl,
HWND hwnd,
USHORT msg,
USHORT wp,
LONG lp
)
{
PPIX ppix = NULL;
switch (msg)
{
// *** NOTE: Only windowed controls receive WM_PAINT
case WM_PAINT:
{
RECT rect;
GetClientRect(hwnd, &rect);
if (wp)
PaintPix(hctl, (HDC)wp, &rect);
else
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
PaintPix(hctl, ps.hdc, &rect);
EndPaint(hwnd, &ps);
}
return 0L;
}
// *** NOTE: Only Graphical controls receive VBM_PAINT
case VBM_PAINT:
PaintPix(hctl, (HDC)wp, (LPRECT)lp);
return 0L;
// *** NOTE: Both Graphical and windowed controls receive WM_NCCREATE
case WM_NCCREATE:
// When being created, let's clear the CTLFLG_GRAPHICALTRANSLUCENT
// which is set by default for Graphical controls.
if (VBGetVersion() >= VB200_VERSION)
{
VBSetControlFlags(hctl, CTLFLG_GRAPHICALTRANSLUCENT, 0);
VBSetControlFlags(hctl, CTLFLG_USESPALETTE, CTLFLG_USESPALETTE);
}
break;
// *** NOTE: Both Graphical and windowed controls receive WM_NCDESTROY
case WM_NCDESTROY:
ppix = (PPIX)VBDerefControl(hctl);
VBFreePic(ppix->hpicPict);
ppix = (PPIX)VBDerefControl(hctl);
if (ppix->hlstrMyTag)
VBDestroyHlstr(ppix->hlstrMyTag);
ppix = (PPIX)VBDerefControl(hctl);
if (ppix->hlstrMyTagMsg)
VBDestroyHlstr(ppix->hlstrMyTagMsg);
break;
case VBM_GETPROPERTY:
switch (wp)
{
case IPROP_PIX_LIST: // Get element of List prop array
{
LONG i;
LPDATASTRUCT lpds = (LPDATASTRUCT)lp;
LPSTR lpstr;
i = lpds->index[0].data;
if (i < 0 || i >= ARRMAX)
return ERR_BadIndex;
ppix = (PPIX)VBDerefControl(hctl);
if (ppix->List[i] == NULL)
{
lpds->data = (LONG)VBCreateHsz((_segment)hctl,"");
// *** ppix may now be invalid due to call to VB API ***
return ERR_None;
}
lpstr = VBDerefHsz(ppix->List[i]);
lpds->data = (LONG)VBCreateHsz((_segment)hctl, lpstr);
// *** ppix may now be invalid due to call to VB API ***
return ERR_None;
}
case IPROP_PIX_MYTAG:
// WARNING: For DT_HLSTR properties which use PF_fGetData,
// WARNING: we must ensure that NULL is never returned!
// WARNING: So, if *lp is NULL, let's create a zero-
// WARNING: length hlstr, and return that!
if (*(HLSTR FAR *)lp == NULL)
{
*(HLSTR FAR *)lp = VBCreateHlstr(NULL, 0);
if (*(HLSTR FAR *)lp == NULL)
return ERR_OutOfMemory;
}
return ERR_None;
case IPROP_PIX_MYTAGMSG:
{
HLSTR hlstr = LppixDEREF(hctl)->hlstrMyTagMsg;
USHORT cb = VBGetHlstrLen(hlstr);
HLSTR hlstrNew = VBCreateHlstr(NULL, cb);
ERR err;
if (!hlstrNew)
return ERR_OutOfMemory;
err = VBSetHlstr(&hlstrNew, VBDerefHlstr(hlstr), cb);
if (err)
{
if (hlstrNew)
VBDestroyHlstr(hlstrNew);
return err;
}
*(HLSTR FAR *)lp = hlstrNew;
return ERR_None;
}
}
break;
case VBM_SETPROPERTY:
switch (wp)
{
case IPROP_PIX_LIST: // Set element of List prop array
{
LONG i;
LPDATASTRUCT lpds =(LPDATASTRUCT)lp;
HSZ hsz;
i = lpds->index[0].data;
if (i < 0 || i >= ARRMAX)
return ERR_BadIndex;
ppix = (PPIX)VBDerefControl(hctl);
if (ppix->List[i])
VBDestroyHsz(ppix->List[i]);
hsz = VBCreateHsz((_segment)hctl, (LPSTR)(lpds->data));
// *** ppix may now be invalid due to call to VB API ***
ppix = (PPIX)VBDerefControl(hctl);
ppix->List[i] = hsz;
return ERR_None;
}
case IPROP_PIX_PICT:
if (VBGetVersion() >= VB200_VERSION)
VBLinkPostAdvise(hctl);
return ERR_None;
case IPROP_PIX_MYTAGMSG:
// WARNING: We must never call VBGetHlstr() in response
// WARNING: to VBM_SETPROPERTY, since this VB API
// WARNING: has the side affect of freeing the hlstr
// WARNING: passed in, if it was a temp hlstr.
// WARNING: Since we do not own the hlstr, we are
// WARNING: forbidden to free it, and hence must not
// WARNING: call VBGetHlstr() or VBDestroyHlstr()
// WARNING: on the hlstr passed in lp. We also cannot
// WARNING: call VBSetHlstr(xx,lp,-1), since this form
// WARNING: of VBSetHlstr() will also free lp if it is a
// WARNING: temp string.
return ErrCopyHlstr(&LppixDEREF(hctl)->hlstrMyTagMsg, (HLSTR)lp);
}
break;
case VBM_CHECKPROPERTY:
switch (wp)
{
case IPROP_PIX_PICT:
{
PIC pic;
if (VBGetVersion() >= VB200_VERSION)
{
// Need to call VBGetPicEx to get the
// hpal field to be filled in
VBGetPicEx((HPIC)lp, &pic, VB_VERSION);
// Mark palette aware, as necessary
VBSetControlFlags(hctl, CTLFLG_HASPALETTE,
(pic.picType == PICTYPE_BITMAP &&
pic.picData.bmp.hpal != NULL)
? CTLFLG_HASPALETTE
: 0);
}
else
VBGetPic((HPIC)lp, &pic);
switch (pic.picType)
{
case PICTYPE_BITMAP:
if (VBGetVersion() >= VB200_VERSION)
{
VBInvalidateRect(hctl, NULL, TRUE);
VBSetControlFlags(hctl,
CTLFLG_GRAPHICALOPAQUE,
CTLFLG_GRAPHICALOPAQUE);
}
else
InvalidateRect(hwnd, NULL, TRUE);
return ERR_None;
case PICTYPE_NONE:
if (VBGetVersion() >= VB200_VERSION)
{
VBInvalidateRect(hctl, NULL, TRUE);
VBSetControlFlags(hctl,
CTLFLG_GRAPHICALOPAQUE|CTLFLG_GRAPHICALTRANSLUCENT,
0);
}
else
InvalidateRect(hwnd, NULL, TRUE);
return ERR_None;
// *** NOTE: If we supported PICTYPE_ICON, we would
// *** NOTE: have to set CTLFLG_GRAPHICALTRANSLUCENT!
}
return VBSetErrorMessage(ERR_BadPixFmt,
"Picture format not supported.");
}
}
break;
case VBM_GETPALETTE:
{
PIC pic;
// Note that this message will only be sent under
// VB 2.0 or higher. Therefore there is no need
// to check the VB version in processing this message.
ppix = (PPIX)VBDerefControl(hctl);
VBGetPicEx(ppix->hpicPict, &pic, VB_VERSION);
if (pic.picType == PICTYPE_BITMAP)
return (LONG)(SHORT)pic.picData.bmp.hpal;
else
return NULL;
}
case VBM_LINKENUMFORMATS:
if (LOWORD(lp) == 0)
return CF_BITMAP;
return NULL;
case VBM_LINKGETDATA:
{
HPIC hpic;
PIC pic;
// Bitmaps and DIB's and metafiles are special cases for DDE.
// HBITMAPS, DIB's and metafiles are not passed directly, but
// instead are passed in a block of memory which contains the
// HBITMAP, handles to DIBs or metafiles. All other formats are
// passed directly. CF_TEXT, for instance, can be accessed
// directly as (LPSZ)GlobalLock(((LPLINKDATA)lp)->hData).
// Note that DIB's are the preferred format for DDE: when
// bitmaps are passed between applications, palette information
// is not included, leading to problems when transferring 256
// bitmaps.
if (wp != CF_BITMAP)
return LINK_DATA_FORMATBAD;
hpic = ((PPIX)VBDerefControl(hctl))->hpicPict;
VBGetPicEx(hpic, &pic, VB_VERSION);
if (pic.picType == PICTYPE_BITMAP)
{
BITMAP bmp;
LONG lDataLen;
HANDLE hData, hDdeData;
LPHANDLE lphnd;
char FAR *pch;
// All data allocated, regardless of format, must be
// GMEM_MOVEABLE and GMEM_DDESHARE.
hDdeData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
sizeof(pic.picData.bmp.hbitmap) + 1);
if (!hDdeData)
return LINK_DATA_OOM;
// Copy the bitmap
if (!GetObject(pic.picData.bmp.hbitmap, sizeof(BITMAP),
(LPSTR)&bmp))
return LINK_DATA_OOM;
lDataLen = (LONG)bmp.bmHeight * bmp.bmWidthBytes *
bmp.bmPlanes;
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
lDataLen);
if (!hData)
return LINK_DATA_OOM;
pch = GlobalLock(hData);
if (!GetBitmapBits((HBITMAP)pic.picData.bmp.hbitmap,
lDataLen, pch))
return LINK_DATA_OOM;
lphnd = (LPHANDLE) GlobalLock(hDdeData);
*lphnd = CreateBitmap(bmp.bmWidth, bmp.bmHeight,
bmp.bmPlanes, bmp.bmBitsPixel,
pch);
GlobalUnlock(hData);
GlobalFree(hData);
GlobalUnlock(hDdeData);
((LPLINKDATA)lp)->cb = sizeof(hDdeData);
((LPLINKDATA)lp)->hData = hDdeData;
return LINK_DATA_OK;
}
else
return LINK_DATA_FORMATBAD;
}
case VBM_LINKSETDATA:
{
HPIC hpic;
LPVOID lpv;
// Bitmaps and DIB's and metafiles are special cases for DDE.
// HBITMAPS, DIB's and metafiles are not passed directly, but
// instead are passed in a block of memory which contains the
// HBITMAP, handles to DIBs or metafiles. All other formats are
// passed directly. CF_TEXT, for instance, can be accessed
// directly as (LPSZ)GlobalLock(((LPLINKDATA)lp)->hData).
// Note that DIB's are the preferred format for DDE: when
// bitmaps are passed between applications, palette information
// is not included, leading to problems when transferring 256
// bitmaps.
// Assure that the clipboard format is of type text.
if (wp != CF_BITMAP)
return LINK_DATA_FORMATBAD;
lpv = GlobalLock(((LPLINKDATA)lp)->hData);
VBPicFromCF((HPIC FAR *) &hpic, *(HANDLE far *)lpv, wp);
GlobalUnlock(((LPLINKDATA)lp)->hData);
if (VBSetControlProperty(hctl, IPROP_PIX_PICT, (LONG)hpic))
return LINK_DATA_SETFAILED;
return LINK_DATA_OK;
}
case VBM_QPASTEOK:
if (wp == PT_PASTELINK)
return VBPasteLinkOk(NULL, hctl);
break;
}
return VBDefControlProc(hctl, hwnd, msg, wp, lp);
}
//---------------------------------------------------------------------------
// Paint the bitmap into the Pix control.
//---------------------------------------------------------------------------
VOID NEAR PaintPix
(
HCTL hctl,
HDC hdc,
LPRECT lprect
)
{
HPIC hpic;
PIC pic;
BITMAP bmp;
HDC hdcMem;
HPEN hpen, hpenOld;
HPALETTE hpalSave = NULL;
HPALETTE hpalOld = NULL;
// Draw a border
hpen = CreatePen(0, 1, COLOR_DEFBITON | COLOR_WINDOWFRAME);
if (hpen)
hpenOld = SelectObject(hdc, (HANDLE)hpen);
Rectangle(hdc, lprect->left, lprect->top, lprect->right, lprect->bottom);
if (hpen && hpenOld)
{
SelectObject(hdc, (HANDLE)hpenOld);
DeleteObject((HANDLE)hpen);
}
// Paint the bitmap, if there is one
hpic = ((PPIX)VBDerefControl(hctl))->hpicPict;
if (VBGetVersion() >= VB200_VERSION)
VBGetPicEx(hpic, &pic, VB_VERSION);
else
{
// Initialize the hpal field to NULL since VBGetPic will not
// do it.
pic.picData.bmp.hpal = NULL;
VBGetPic(hpic, &pic);
}
switch (pic.picType)
{
case PICTYPE_BITMAP:
GetObject(pic.picData.bmp.hbitmap, sizeof(BITMAP), (LPSTR)&bmp);
hdcMem = CreateCompatibleDC(hdc);
if (pic.picData.bmp.hpal)
{
if (!PictFMemDC(hdc))
{
// If the hdc is a memory DC, then PictStretchBlt will use
// the palette of the destination DC correctly.
// One condition that the hdc will be a memory dc is when
// the control is being printed. In that case, a rainbow
// palette has already been selected into the hdc and
// will be used for the printing.
// NOTE: If this control was a windowed control under
// NOTE: VB 2.0 of higher, then there is no need to
// NOTE: select the palette into the destination DC
// NOTE: because VB will already have done so.
hpalOld = SelectPalette(hdc, pic.picData.bmp.hpal, TRUE);
RealizePalette(hdc);
}
// If the bitmap has a palette, select it into the memory dc
hpalSave = SelectPalette(hdcMem, pic.picData.bmp.hpal, FALSE);
RealizePalette(hdcMem);
}
SelectObject(hdcMem, pic.picData.bmp.hbitmap);
// Note that since we drew a border, the area into which we
// PictStretchBlt the bitmap is two pixels smaller.
// NOTE: We must use PictStretchBlt instead of StretchBlt
// NOTE: to handle printing 256-color bitmaps!
PictStretchBlt(hdc, lprect->left+1, lprect->top+1,
lprect->right - lprect->left - 2,
lprect->bottom - lprect->top - 2,
hdcMem, 0, 0,
bmp.bmWidth, bmp.bmHeight, SRCCOPY);
if (hpalOld)
{
SelectPalette(hdc, hpalOld, TRUE);
RealizePalette(hdc);
}
if (hpalSave)
{
SelectPalette(hdcMem, hpalSave, FALSE);
RealizePalette(hdcMem);
}
DeleteDC(hdcMem);
break;
case PICTYPE_NONE:
// Remain totally transparent if we don't have a picture
break;
}
}
//---------------------------------------------------------------------------
// Make a copy of hlstrSrc, and store the resulting hlstr in *lphlstrDest.
// On entry *lphlstrDest may be NULL or a valid hlstr. If NULL, a new hlstr
// will be allocated to hold hlstrSrc, and then this handle will be stored
// in *lphlstrDest. If *lphlstrDest was originally non-NULL, then we try
// resizing *lphlstrDest to fit hlstrSrc, and failing that, we free the
// hlstr at *lphlstrDest, and allocate a new hlstr, storing that new handle
// back into *lphlstrDest.
//---------------------------------------------------------------------------
// WARNING: This routine is called from VBM_SETPROPERTY!!!! We must never
// WARNING: call VBGetHlstr() in response to VBM_SETPROPERTY, since this VB
// WARNING: API has the side affect of freeing the hlstr passed in, if it was
// WARNING: a temp hlstr. Since we do not own the hlstr, we are forbidden to
// WARNING: free it, and hence must not call VBGetHlstr() or VBDestroyHlstr()
// WARNING: on the hlstr passed in lp. We also cannot call
// WARNING: VBSetHlstr(xx,lp,-1), since this form of VBSetHlstr() will also
// WARNING: free lp if it is a temp string.
//---------------------------------------------------------------------------
ERR ErrCopyHlstr
(
HLSTR FAR *lphlstrDest,
HLSTR hlstrSrc
)
{
ERR err;
HLSTR hlstrOld = *lphlstrDest;
USHORT cb = VBGetHlstrLen(hlstrSrc);
HLSTR hlstrNew;
// To prevent using excessive amts of memory, let's just try re-allocate
// this hlstr in place.
if (hlstrOld)
{
err = VBResizeHlstr(hlstrOld, cb);
if (!err)
{
// Successful, so lets copy the string data and return
return VBSetHlstr(lphlstrDest, VBDerefHlstr(hlstrSrc), cb);
}
}
// Unsuccessful at re-allocating in place. So, we'll now try allocating
// a *new* hlstr to contain lp, since VBResizeHlstr() didn't try
// allocating in a new segment. Note we cannot do
// VBCreateHlstr(VBDerefHlstr(hlstrSrc), cb), since the create might
// cause hlstrSrc to move after we've already Deref'd it.
hlstrNew = VBCreateHlstr(NULL, cb);
if (!hlstrNew)
return ERR_OutOfMemory;
// Successful, so lets copy the string data
err = VBSetHlstr(&hlstrNew, VBDerefHlstr(hlstrSrc), cb);
if (err)
{
// Failed, so let's clean up and return the error
if (hlstrNew)
VBDestroyHlstr(hlstrNew);
return err;
}
// Success. Let's keep the new value, and free the old
*lphlstrDest = hlstrNew;
if (hlstrOld)
VBDestroyHlstr(hlstrOld);
return ERR_None;
}
//---------------------------------------------------------------------------
// Register custom control. This routine is called by VB when the custom
// control DLL is loaded for use.
//---------------------------------------------------------------------------
BOOL FAR PASCAL _export VBINITCC
(
USHORT usVersion,
BOOL fRuntime
)
{
// Avoid warnings on unused (but required) formal parameters
fRuntime = fRuntime;
// Register control(s)
if (usVersion < VB_VERSION)
return VBRegisterModel(hmodDLL, &modelPix_Vb1);
else
return VBRegisterModel(hmodDLL, &modelPix);
}
//---------------------------------------------------------------------------
// Provide custom control model information to host environment.
//---------------------------------------------------------------------------
LPMODELINFO FAR PASCAL _export VBGetModelInfo
(
USHORT usVersion
)
{
if (usVersion < VB_VERSION)
return &modelinfoPix_Vb1;
else
return &modelinfoPix;
}
//---------------------------------------------------------------------------
// Initialize library. This routine is called when the first client loads
// the DLL.
//---------------------------------------------------------------------------
int FAR PASCAL LibMain
(
HANDLE hModule,
WORD wDataSeg,
WORD cbHeapSize,
LPSTR lpszCmdLine
)
{
// Avoid warnings on unused (but required) formal parameters
wDataSeg = wDataSeg;
cbHeapSize = cbHeapSize;
lpszCmdLine = lpszCmdLine;
hmodDLL = hModule;
return 1;
}
//---------------------------------------------------------------------------
// WEP
//---------------------------------------------------------------------------
// C7 and QCWIN provide default a WEP:
//---------------------------------------------------------------------------
#if (_MSC_VER < 610)
int FAR PASCAL WEP(int fSystemExit);
//---------------------------------------------------------------------------
// For Windows 3.0 it is recommended that the WEP function reside in a
// FIXED code segment and be exported as RESIDENTNAME. This is
// accomplished using the alloc_text pragma below and the related EXPORTS
// and SEGMENTS directives in the .DEF file.
//
// Read the comments section documenting the WEP function in the Windows
// 3.1 SDK "Programmers Reference, Volume 2: Functions" before placing
// any additional code in the WEP routine for a Windows 3.0 DLL.
//---------------------------------------------------------------------------
#pragma alloc_text(WEP_TEXT,WEP)
//---------------------------------------------------------------------------
// Performs cleanup tasks when the DLL is unloaded. WEP() is
// called automatically by Windows when the DLL is unloaded (no
// remaining tasks still have the DLL loaded). It is strongly
// recommended that a DLL have a WEP() function, even if it does
// nothing but returns success (1), as in this example.
//---------------------------------------------------------------------------
int FAR PASCAL WEP
(
int fSystemExit
)
{
// Avoid warnings on unused (but required) formal parameters
fSystemExit = fSystemExit;
return 1;
}
#endif
//---------------------------------------------------------------------------