791 lines
22 KiB
C++
791 lines
22 KiB
C++
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// File: image.cpp
|
||
|
//
|
||
|
// Module: CMDIAL and CMAK
|
||
|
//
|
||
|
// Synopsis: CMDIAL/CMAK specific imaging support routines
|
||
|
//
|
||
|
// Copyright (c) 1998-1999 Microsoft Corporation
|
||
|
//
|
||
|
// Author: nickball Created Header 03/30/98
|
||
|
// quintinb moved to common\source 08/06/98
|
||
|
//
|
||
|
//+----------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CmGetBitmapInfo
|
||
|
//
|
||
|
// Synopsis: Helper function to retrieve the contents of a bitmap from an HBITMAP
|
||
|
//
|
||
|
// Arguments: hbm - Hanhdle of the target bitmap
|
||
|
//
|
||
|
// Returns: A pointer to a LPBITMAPINFO that contains the INFOHEADER,
|
||
|
// ColorTable and bits for the bitmap.
|
||
|
//
|
||
|
// Note: When accessing this value, or passing it on to other BITMAP APIs
|
||
|
// it is recommended that the value be cast as an (LPBYTE).
|
||
|
//
|
||
|
// History: a-nichb - Cleaned-up and commented - 3/21/97
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
LPBITMAPINFO CmGetBitmapInfo(HBITMAP hbm)
|
||
|
{
|
||
|
LPBITMAPINFO pbmi = NULL;
|
||
|
HDC hDC = NULL;
|
||
|
int nNumColors = 0;
|
||
|
int iRes;
|
||
|
LPBITMAPINFO lpbmih = NULL;
|
||
|
DWORD dwInfoSize = 0;
|
||
|
WORD wbiBits = 0;
|
||
|
|
||
|
if (!hbm)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// Get the basic bmp object info
|
||
|
|
||
|
BITMAP BitMap;
|
||
|
|
||
|
if (!GetObjectA(hbm, sizeof(BITMAP), &BitMap))
|
||
|
{
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// Calc the color bits and num colors
|
||
|
|
||
|
wbiBits = BitMap.bmPlanes * BitMap.bmBitsPixel;
|
||
|
|
||
|
if (wbiBits <= 8)
|
||
|
{
|
||
|
nNumColors = 1 << wbiBits;
|
||
|
}
|
||
|
|
||
|
// Allocate a BITMAPINFO structure large enough to hold header + color palette
|
||
|
|
||
|
dwInfoSize = sizeof(BITMAPINFOHEADER) + (nNumColors * sizeof(RGBQUAD));
|
||
|
|
||
|
lpbmih = (LPBITMAPINFO) CmMalloc(dwInfoSize);
|
||
|
|
||
|
if (!lpbmih)
|
||
|
{
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// Pre-fill the info that we have about the bmp
|
||
|
|
||
|
lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||
|
lpbmih->bmiHeader.biWidth = BitMap.bmWidth;
|
||
|
lpbmih->bmiHeader.biHeight = BitMap.bmHeight;
|
||
|
lpbmih->bmiHeader.biPlanes = 1;
|
||
|
lpbmih->bmiHeader.biBitCount = wbiBits;
|
||
|
|
||
|
// Call GetDiBits() w/ 5th Param to NULL, this is treated by the system as
|
||
|
// a query in which case it validates the lpbmih contents and fills in the
|
||
|
// biSizeImage member of the structure
|
||
|
|
||
|
hDC = GetDC(NULL);
|
||
|
if (!hDC)
|
||
|
{
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
iRes = GetDIBits(hDC,hbm,0,BitMap.bmHeight,NULL,(LPBITMAPINFO) lpbmih,DIB_RGB_COLORS);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (!iRes)
|
||
|
{
|
||
|
CMTRACE(TEXT("CmGetBitmapInfo() GetDIBits() failed."));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (iRes)
|
||
|
{
|
||
|
DWORD dwFullSize = dwInfoSize;
|
||
|
|
||
|
// Create a complete DIB structure with room for bits and fill it
|
||
|
|
||
|
if (lpbmih->bmiHeader.biSizeImage)
|
||
|
{
|
||
|
dwFullSize += lpbmih->bmiHeader.biSizeImage;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwFullSize += (((WORD) (lpbmih->bmiHeader.biWidth * lpbmih->bmiHeader.biBitCount) / 8) * (WORD) BitMap.bmHeight);
|
||
|
}
|
||
|
|
||
|
pbmi = (LPBITMAPINFO) CmMalloc(dwFullSize + sizeof(DWORD));
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
*((DWORD *) (((PBYTE) pbmi)+dwFullSize)) = 0x12345678;
|
||
|
*((DWORD *) (((PBYTE) pbmi)+dwFullSize-sizeof(DWORD))) = 0x23456789;
|
||
|
#endif
|
||
|
|
||
|
if (pbmi)
|
||
|
{
|
||
|
// Load the new larger LPBITMAPINFO struct with existing info,
|
||
|
// and get the data bits. Release the existing LPBITMAPINFO.
|
||
|
|
||
|
CopyMemory(pbmi, lpbmih, dwInfoSize);
|
||
|
|
||
|
//
|
||
|
// We have a handle, we want the exact bits.
|
||
|
//
|
||
|
|
||
|
iRes = GetDIBits(hDC,
|
||
|
hbm,
|
||
|
0,
|
||
|
BitMap.bmHeight,
|
||
|
((LPBYTE) pbmi) + dwInfoSize,
|
||
|
pbmi,
|
||
|
DIB_RGB_COLORS);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (*((DWORD *) (((PBYTE) pbmi) + dwFullSize)) != 0x12345678)
|
||
|
{
|
||
|
CMTRACE(TEXT("CmGetBitmapInfo() GetDIBits() copied too much."));
|
||
|
}
|
||
|
|
||
|
if (*((DWORD *) (((PBYTE) pbmi) + dwFullSize - sizeof(DWORD))) == 0x23456789)
|
||
|
{
|
||
|
CMTRACE(TEXT("CmGetBitmapInfo() GetDIBits() didn't copy enough."));
|
||
|
}
|
||
|
#endif
|
||
|
// If GetDiBits() failed, free the BITMAPINFO buffer
|
||
|
|
||
|
if (!iRes)
|
||
|
{
|
||
|
CmFree(pbmi);
|
||
|
pbmi = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Cleanup
|
||
|
|
||
|
Cleanup:
|
||
|
if (lpbmih)
|
||
|
{
|
||
|
CmFree(lpbmih);
|
||
|
}
|
||
|
if (hDC)
|
||
|
{
|
||
|
ReleaseDC(NULL, hDC);
|
||
|
}
|
||
|
|
||
|
return pbmi;
|
||
|
}
|
||
|
|
||
|
static HPALETTE CmCreateDIBPalette(LPBITMAPINFO pbmi)
|
||
|
{
|
||
|
WORD wNumColors = 0;
|
||
|
HPALETTE hRes = NULL;
|
||
|
|
||
|
if (!pbmi)
|
||
|
{
|
||
|
return (NULL);
|
||
|
}
|
||
|
|
||
|
// Get num colors according to color depth
|
||
|
// Note: 24-bit bitmaps have no color table
|
||
|
|
||
|
if (pbmi->bmiHeader.biBitCount <= 8)
|
||
|
{
|
||
|
wNumColors = 1 << pbmi->bmiHeader.biBitCount;
|
||
|
}
|
||
|
|
||
|
// Fill logical palette based upon color table
|
||
|
|
||
|
if (wNumColors)
|
||
|
{
|
||
|
LPLOGPALETTE pLogPal;
|
||
|
int idx;
|
||
|
|
||
|
pLogPal = (LPLOGPALETTE) CmMalloc(sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*wNumColors);
|
||
|
if (pLogPal)
|
||
|
{
|
||
|
pLogPal->palVersion = 0x300;
|
||
|
pLogPal->palNumEntries = wNumColors;
|
||
|
for (idx=0;idx<wNumColors;idx++)
|
||
|
{
|
||
|
pLogPal->palPalEntry[idx].peRed = pbmi->bmiColors[idx].rgbRed;
|
||
|
pLogPal->palPalEntry[idx].peGreen = pbmi->bmiColors[idx].rgbGreen;
|
||
|
pLogPal->palPalEntry[idx].peBlue = pbmi->bmiColors[idx].rgbBlue;
|
||
|
pLogPal->palPalEntry[idx].peFlags = 0;
|
||
|
}
|
||
|
|
||
|
// Create a new palette
|
||
|
|
||
|
hRes = CreatePalette(pLogPal);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (!hRes)
|
||
|
{
|
||
|
CMTRACE1(TEXT("CmCreateDIBPalette() CreatePalette() failed, GLE=%u."), GetLastError());
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
CmFree(pLogPal);
|
||
|
}
|
||
|
}
|
||
|
return hRes;
|
||
|
}
|
||
|
|
||
|
HBITMAP CmLoadBitmap(HINSTANCE hInst, LPCTSTR pszSpec)
|
||
|
{
|
||
|
return ((HBITMAP) CmLoadImage(hInst, pszSpec, IMAGE_BITMAP, 0, 0));
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ReleaseBitmapData
|
||
|
//
|
||
|
// Synopsis: Releases resources and memory acquired during CreateBitmapData. Note
|
||
|
// that if you are using this with the BmpWndProc function below, that you
|
||
|
// should call an STM_SETIMAGE with a NULL image pointer param in order to
|
||
|
// clear out the window procedures window long. Otherwise, it could get
|
||
|
// a WM_PAINT message and try to use the freed memory before you can
|
||
|
// clear it out or have the window destroyed by the dialog manager.
|
||
|
//
|
||
|
// Arguments: LPBMPDATA pBmpData - Ptr to the BmpData to be released
|
||
|
//
|
||
|
// Returns: Nothing
|
||
|
//
|
||
|
// History: nickball Created 3/27/98
|
||
|
//
|
||
|
//+----------------------------------------------------------------------------
|
||
|
void ReleaseBitmapData(LPBMPDATA pBmpData)
|
||
|
{
|
||
|
MYDBGASSERT(pBmpData);
|
||
|
|
||
|
if (NULL == pBmpData)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (pBmpData->hDIBitmap)
|
||
|
{
|
||
|
DeleteObject(pBmpData->hDIBitmap);
|
||
|
pBmpData->hDIBitmap = NULL;
|
||
|
}
|
||
|
|
||
|
if (pBmpData->hDDBitmap)
|
||
|
{
|
||
|
DeleteObject(pBmpData->hDDBitmap);
|
||
|
pBmpData->hDDBitmap = NULL;
|
||
|
}
|
||
|
|
||
|
if (pBmpData->pBmi)
|
||
|
{
|
||
|
CmFree(pBmpData->pBmi);
|
||
|
pBmpData->pBmi = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CreateBitmapData
|
||
|
//
|
||
|
// Synopsis: Fills a BMPDATA struct with all data necessary to display a bitmap.
|
||
|
//
|
||
|
// Arguments: HBITMAP hBmp - Handle of the source bitmap
|
||
|
// LPBMPDATA lpBmpData - Ptr to the BmpData struct to be filled
|
||
|
// HWND hwnd - The hwnd that the bitmap will be displayed in.
|
||
|
// BOOL fCustomPalette - Indicates that the DDB should be created with a palette specific to the bitmap.
|
||
|
//
|
||
|
// Returns: BOOL - TRUE on succes
|
||
|
//
|
||
|
// History: nickball Created 3/27/98
|
||
|
//
|
||
|
//+----------------------------------------------------------------------------
|
||
|
BOOL CreateBitmapData(HBITMAP hDIBmp,
|
||
|
LPBMPDATA lpBmpData,
|
||
|
HWND hwnd,
|
||
|
BOOL fCustomPalette)
|
||
|
{
|
||
|
MYDBGASSERT(hDIBmp);
|
||
|
MYDBGASSERT(lpBmpData);
|
||
|
MYDBGASSERT(lpBmpData->phMasterPalette);
|
||
|
|
||
|
if (NULL == hDIBmp || NULL == lpBmpData)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Params look good, get busy
|
||
|
//
|
||
|
|
||
|
HPALETTE hPaletteNew = NULL;
|
||
|
LPBITMAPINFO pBmi = NULL;
|
||
|
HBITMAP hDDBmp = NULL;
|
||
|
HDC hDC;
|
||
|
int iRes = 0;
|
||
|
|
||
|
//
|
||
|
// If we already have a pBmi value, we will assume it is up to date, as
|
||
|
// both it and the DIB do not change throughout the life of the BMP.
|
||
|
// Note: If BmpData is not zero initialized, you will have problems.
|
||
|
//
|
||
|
|
||
|
if (lpBmpData->pBmi)
|
||
|
{
|
||
|
pBmi = lpBmpData->pBmi;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Use the bitmap handle to retrieve a BITMAPINFO ptr complete w/ data
|
||
|
//
|
||
|
|
||
|
pBmi = CmGetBitmapInfo(lpBmpData->hDIBitmap);
|
||
|
|
||
|
if (NULL == pBmi)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// we need a DC
|
||
|
//
|
||
|
|
||
|
hDC = GetDC(hwnd);
|
||
|
|
||
|
if (!hDC)
|
||
|
{
|
||
|
CMTRACE(TEXT("MyCreateDDBitmap() GetDC() failed."));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If CM is localized so that it is RTL (Right to Left => arabic and Hebrew),
|
||
|
// then we need to call SetLayout on the hDC from above. If we don't
|
||
|
// set the layout back to LTR, the bitmap will show up as all black instead of as
|
||
|
// an image.
|
||
|
//
|
||
|
HMODULE hLib = LoadLibrary(TEXT("gdi32.dll"));
|
||
|
|
||
|
if (hLib)
|
||
|
{
|
||
|
#ifndef LAYOUT_RTL
|
||
|
#define LAYOUT_RTL 0x00000001 // Right to left
|
||
|
#endif
|
||
|
|
||
|
DWORD dwLayout;
|
||
|
typedef DWORD (WINAPI* pfnSetLayoutType)(HDC, DWORD);
|
||
|
typedef DWORD (WINAPI* pfnGetLayoutType)(HDC);
|
||
|
|
||
|
pfnSetLayoutType pfnSetLayout = (pfnSetLayoutType)GetProcAddress(hLib, "SetLayout");
|
||
|
pfnGetLayoutType pfnGetLayout = (pfnGetLayoutType)GetProcAddress(hLib, "GetLayout");
|
||
|
|
||
|
if (pfnSetLayout && pfnGetLayout)
|
||
|
{
|
||
|
DWORD dwLayout = pfnGetLayout(hDC);
|
||
|
|
||
|
if (LAYOUT_RTL & dwLayout)
|
||
|
{
|
||
|
dwLayout ^= LAYOUT_RTL; // toggle LAYOUT_RTL off
|
||
|
pfnSetLayout(hDC, dwLayout);
|
||
|
CMTRACE(TEXT("CreateBitmapData -- Toggling off LAYOUT_RTL on the device context"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FreeLibrary(hLib);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If fCustomPalette is set then create a palette based on our bits
|
||
|
// and realize it in the current DC.
|
||
|
//
|
||
|
|
||
|
if (fCustomPalette)
|
||
|
{
|
||
|
hPaletteNew = CmCreateDIBPalette(pBmi);
|
||
|
|
||
|
if (hPaletteNew)
|
||
|
{
|
||
|
//
|
||
|
// Select and realize the new palette so that the DDB is created with it below
|
||
|
//
|
||
|
|
||
|
HPALETTE hPalettePrev = SelectPalette(hDC,
|
||
|
hPaletteNew, lpBmpData->bForceBackground); // FALSE == Foreground app behavior);
|
||
|
// TRUE == Background app behavior);
|
||
|
|
||
|
if (hPalettePrev)
|
||
|
{
|
||
|
iRes = RealizePalette(hDC);
|
||
|
#ifdef DEBUG
|
||
|
if (GDI_ERROR == iRes)
|
||
|
{
|
||
|
CMTRACE1(TEXT("MyCreateDDBitmap() RealizePalette() failed, GLE=%u."), GetLastError());
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CMTRACE1(TEXT("MyCreateDDBitmap() SelectPalette() failed, GLE=%u."), GetLastError());
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Determine number of color entries based upon color depth
|
||
|
//
|
||
|
|
||
|
int nNumColors = 0;
|
||
|
|
||
|
if (pBmi->bmiHeader.biBitCount <= 8)
|
||
|
{
|
||
|
nNumColors = (1 << pBmi->bmiHeader.biBitCount);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create the DDB from the bits
|
||
|
//
|
||
|
|
||
|
hDDBmp = CreateDIBitmap(hDC,
|
||
|
&pBmi->bmiHeader,
|
||
|
CBM_INIT,
|
||
|
((LPBYTE) pBmi) + sizeof(BITMAPINFOHEADER) + (nNumColors * sizeof(RGBQUAD)), //dib.dsBm.bmBits,
|
||
|
pBmi,
|
||
|
DIB_RGB_COLORS);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (!hDDBmp)
|
||
|
{
|
||
|
CMTRACE(TEXT("MyCreateDDBitmap() CreateDIBitmap() failed."));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
ReleaseDC(NULL, hDC);
|
||
|
|
||
|
//
|
||
|
// Fill in the bitmap data
|
||
|
//
|
||
|
|
||
|
if (hDDBmp)
|
||
|
{
|
||
|
lpBmpData->hDIBitmap = hDIBmp;
|
||
|
lpBmpData->pBmi = pBmi;
|
||
|
|
||
|
//
|
||
|
// Delete existing DDB, if any
|
||
|
//
|
||
|
|
||
|
if (lpBmpData->hDDBitmap)
|
||
|
{
|
||
|
DeleteObject(lpBmpData->hDDBitmap);
|
||
|
}
|
||
|
|
||
|
lpBmpData->hDDBitmap = hDDBmp;
|
||
|
|
||
|
if (hPaletteNew)
|
||
|
{
|
||
|
//
|
||
|
// Delete existing Palette, if any
|
||
|
//
|
||
|
|
||
|
if (*lpBmpData->phMasterPalette)
|
||
|
{
|
||
|
DeleteObject(*lpBmpData->phMasterPalette);
|
||
|
}
|
||
|
|
||
|
*lpBmpData->phMasterPalette = hPaletteNew;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Something went wrong, cleanup
|
||
|
//
|
||
|
|
||
|
CmFree(pBmi);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Bitmap window procedure
|
||
|
//
|
||
|
|
||
|
LRESULT CALLBACK BmpWndProc(HWND hwndBmp,
|
||
|
UINT uMsg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam)
|
||
|
{
|
||
|
LPBMPDATA pBmpData = (LPBMPDATA) GetWindowLongU(hwndBmp,0);
|
||
|
BOOL bRes;
|
||
|
|
||
|
switch (uMsg)
|
||
|
{
|
||
|
case WM_CREATE:
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
SetWindowLongU(hwndBmp,sizeof(LPBMPDATA),(LONG_PTR) NULL);
|
||
|
break;
|
||
|
|
||
|
case WM_PAINT:
|
||
|
if (pBmpData && pBmpData->pBmi)
|
||
|
{
|
||
|
LPBITMAPINFO pBmi = pBmpData->pBmi;
|
||
|
|
||
|
RECT rWnd;
|
||
|
RECT rSrc = {0,0,(int)pBmpData->pBmi->bmiHeader.biWidth,
|
||
|
(int)pBmpData->pBmi->bmiHeader.biHeight};
|
||
|
PAINTSTRUCT ps;
|
||
|
HDC hdcBmp;
|
||
|
HBITMAP hbmpPrev;
|
||
|
int iPrevStretchMode;
|
||
|
|
||
|
//
|
||
|
// Start painting
|
||
|
//
|
||
|
|
||
|
HDC hdc = BeginPaint(hwndBmp,&ps);
|
||
|
|
||
|
if (hdc)
|
||
|
{
|
||
|
//
|
||
|
// Select and realize our current palette in the current DC
|
||
|
//
|
||
|
|
||
|
//UnrealizeObject(*pBmpData->phMasterPalette);
|
||
|
SelectPalette(hdc, *pBmpData->phMasterPalette, pBmpData->bForceBackground);
|
||
|
RealizePalette(hdc);
|
||
|
|
||
|
//
|
||
|
// Create a compatible DC, we'll create the BMP here then BLT it to the real DC
|
||
|
//
|
||
|
|
||
|
hdcBmp = CreateCompatibleDC(hdc);
|
||
|
|
||
|
if (hdcBmp)
|
||
|
{
|
||
|
//
|
||
|
// Select and realize our current palette in the compatible DC
|
||
|
//
|
||
|
|
||
|
SelectPalette(hdcBmp, *pBmpData->phMasterPalette, pBmpData->bForceBackground);
|
||
|
RealizePalette(hdcBmp);
|
||
|
|
||
|
if (!hdcBmp)
|
||
|
{
|
||
|
CMTRACE(TEXT("BmpWndProc() CreateCompatibleDC() failed."));
|
||
|
}
|
||
|
|
||
|
if (!pBmpData->hDDBitmap)
|
||
|
{
|
||
|
CMTRACE(TEXT("BmpWndProc() - WM_PAINT - hDDBitmap is NULL."));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Select the bitmap into the compatible DC
|
||
|
//
|
||
|
|
||
|
hbmpPrev = (HBITMAP) SelectObject(hdcBmp,pBmpData->hDDBitmap);
|
||
|
bRes = GetWindowRect(hwndBmp,&rWnd);
|
||
|
|
||
|
if (!bRes)
|
||
|
{
|
||
|
CMTRACE1(TEXT("BmpWndProc() GetWindowRect() failed, GLE=%u."), GetLastError());
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now set the mode, and StretchBlt the bitmap from the compatible DC to the active DC
|
||
|
//
|
||
|
|
||
|
CMTRACE(TEXT("BmpWndProc() : Changing stretch mode"));
|
||
|
iPrevStretchMode = SetStretchBltMode(hdc, STRETCH_DELETESCANS);
|
||
|
|
||
|
bRes = StretchBlt(hdc,
|
||
|
rWnd.left-rWnd.left,
|
||
|
rWnd.top-rWnd.top,
|
||
|
rWnd.right-rWnd.left,
|
||
|
rWnd.bottom-rWnd.top,
|
||
|
hdcBmp,
|
||
|
rSrc.left-rSrc.left,
|
||
|
rSrc.top-rSrc.top,
|
||
|
rSrc.right-rSrc.left,
|
||
|
rSrc.bottom-rSrc.top,
|
||
|
SRCCOPY);
|
||
|
if (!bRes)
|
||
|
{
|
||
|
CMTRACE1(TEXT("BmpWndProc() StretchBlt() failed, GLE=%u."), GetLastError());
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Restore the mode in the active DC
|
||
|
//
|
||
|
CMTRACE(TEXT("BmpWndProc() Restoring stretch mode"));
|
||
|
iPrevStretchMode = SetStretchBltMode(hdc, iPrevStretchMode);
|
||
|
|
||
|
//
|
||
|
// Restore the compatible DC and release it
|
||
|
//
|
||
|
|
||
|
SelectObject(hdcBmp,hbmpPrev);
|
||
|
DeleteDC(hdcBmp);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CMTRACE1(TEXT("BmpWndProc() CreateCompatibleDC() failed, GLE=%u."), GetLastError());
|
||
|
}
|
||
|
|
||
|
|
||
|
bRes = EndPaint(hwndBmp,&ps);
|
||
|
|
||
|
if (!bRes)
|
||
|
{
|
||
|
CMTRACE(TEXT("BmpWndProc() EndPaint() failed."));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CMTRACE1(TEXT("BmpWndProc() BeginPaint() failed, GLE=%u."), GetLastError());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case STM_SETIMAGE:
|
||
|
if (wParam == IMAGE_BITMAP)
|
||
|
{
|
||
|
CMTRACE2(TEXT("STM_SETIMAGE: wParam=%u, lParam=%u"), wParam, lParam);
|
||
|
|
||
|
//
|
||
|
// lParam contains a handle to the bitmap data, store it in extra bytes
|
||
|
//
|
||
|
|
||
|
SetWindowLongU(hwndBmp,0, lParam); // pBmpData
|
||
|
|
||
|
CMTRACE2(TEXT("SetWindowLongU called with hwndBmp = %u, lParam=%u"), hwndBmp, lParam);
|
||
|
|
||
|
//
|
||
|
// Force a repaint
|
||
|
//
|
||
|
|
||
|
bRes = InvalidateRect(hwndBmp,NULL,TRUE);
|
||
|
|
||
|
CMTRACE2(TEXT("InvalidateRect called with hwndBmp = %u, lParam=%u"), hwndBmp, lParam);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (!bRes)
|
||
|
{
|
||
|
CMTRACE(TEXT("BmpWndProc() InvalidateRect() failed."));
|
||
|
}
|
||
|
#endif
|
||
|
if (pBmpData && pBmpData->hDDBitmap)
|
||
|
{
|
||
|
return ((LRESULT) pBmpData->hDDBitmap);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return (DefWindowProcU(hwndBmp,uMsg,wParam,lParam));
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: QueryNewPalette
|
||
|
//
|
||
|
// Synopsis: Helper function to encapsulate handling of WM_QUERYNEWPALETTE
|
||
|
//
|
||
|
// Arguments: hwndDlg - Handle of the dialog receiving the message
|
||
|
// lpBmpData - Struct containing handles for bmp to display
|
||
|
// iBmpCtrl - Bitmap control ID
|
||
|
//
|
||
|
// Returns: Nothing
|
||
|
//
|
||
|
// History: a-nichb - Created - 7/14/97
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void QueryNewPalette(LPBMPDATA lpBmpData, HWND hwndDlg, int iBmpCtrl)
|
||
|
{
|
||
|
MYDBGASSERT(lpBmpData);
|
||
|
|
||
|
if (lpBmpData)
|
||
|
{
|
||
|
//
|
||
|
// We just handle this as a standard palette change because we
|
||
|
// want to ensure that we create a new DDB using a palette based
|
||
|
// upon our bitmap.
|
||
|
//
|
||
|
|
||
|
PaletteChanged(lpBmpData, hwndDlg, iBmpCtrl);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: PaletteChanged
|
||
|
//
|
||
|
// Synopsis: Helper function to encapsulate handling of WM_PALETTECHANGED
|
||
|
//
|
||
|
// Arguments: hwndDlg - Handle of the dialog receiving the message
|
||
|
// lpBmpData - Struct containing handles for bmp to display
|
||
|
// iBmpCtrl - Bitmap control ID
|
||
|
//
|
||
|
// Returns: Nothing
|
||
|
//
|
||
|
// History: a-nichb - Created - 7/14/97
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
void PaletteChanged(LPBMPDATA lpBmpData, HWND hwndDlg, int iBmpCtrl)
|
||
|
{
|
||
|
MYDBGASSERT(lpBmpData);
|
||
|
|
||
|
if (NULL == lpBmpData || NULL == lpBmpData->phMasterPalette)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Unrealize the master palette if it exists
|
||
|
//
|
||
|
|
||
|
if (*lpBmpData->phMasterPalette)
|
||
|
{
|
||
|
UnrealizeObject(*lpBmpData->phMasterPalette);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create a device dependent bitmap and appropriate palette
|
||
|
//
|
||
|
|
||
|
if (CreateBitmapData(lpBmpData->hDIBitmap, lpBmpData, hwndDlg, TRUE))
|
||
|
{
|
||
|
//
|
||
|
// SetImage to update handles for painting and force draw
|
||
|
//
|
||
|
|
||
|
HBITMAP hbmpTmp = (HBITMAP) SendDlgItemMessageA(hwndDlg, iBmpCtrl, STM_SETIMAGE,
|
||
|
IMAGE_BITMAP,(LPARAM) lpBmpData);
|
||
|
#ifdef DEBUUG
|
||
|
if (!hbmpTmp)
|
||
|
{
|
||
|
CMTRACE(TEXT("PaletteChanged().WM_PALETTECHANGED - STM_SETIMAGE returned NULL."));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|