NT4/private/windows/base/advapi/digsig/softpub/licens~1.cpp
2020-09-30 17:12:29 +02:00

999 lines
28 KiB
C++

// LicenseBmp.cpp : implementation file
//
#include "stdpch.h"
#include "common.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// Utility declarations
HBITMAP LoadResourceBitmap(HINSTANCE hInstance, LPSTR lpString, HPALETTE* lphPalette);
LRESULT APIENTRY CLicenseBmpProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#define SELPALMODE TRUE
/////////////////////////////////////////////////////////////////////////////
// CLicenseBmp
CLicenseBmp::CLicenseBmp(CDialogRunOrNot* pdlg)
{
m_pdlg = pdlg;
m_fInitialized = FALSE;
m_hpal = NULL;
m_hbmp = NULL;
m_bmpSeal = NULL;
m_prevProc = NULL;
m_hWnd = NULL;
m_hwndToolTip = NULL;
m_szTestingBanter[0] = 0;
m_hfontTestingBanter = NULL;
m_szFontName[0] = 0;
m_ulFontPitchAndFamily = (VARIABLE_PITCH | FF_SWISS);
m_hlinkHeight = 100;
m_banterHeight = 85;
}
CLicenseBmp::~CLicenseBmp()
{
if (m_hpal != NULL)
{
::DeleteObject(m_hpal);
}
if (m_hbmp != NULL)
{
::DeleteObject(m_hbmp);
}
if (m_bmpSeal != NULL)
{
::DeleteObject(m_bmpSeal);
}
if (m_hfontTestingBanter != NULL)
{
DeleteObject(m_hfontTestingBanter);
}
}
void FormatMessage(HINSTANCE hinst, LPTSTR szMessage, int cbMessage, UINT nFormatID, ...)
{
// get format string from string table
TCHAR szFormat[512];
LoadString(hinst, nFormatID, szFormat, 512);
// format message into requested buffer
va_list argList;
va_start(argList, nFormatID);
::FormatMessage(
FORMAT_MESSAGE_FROM_STRING,
szFormat,
0,
0,
szMessage,
cbMessage,
&argList);
va_end(argList);
}
UINT CLicenseBmp::GetLoc(UINT ids)
{
TCHAR sz[16];
::LoadString(Hinst(), ids, &sz[0], 16);
return (UINT)atol(sz);
}
UINT CLicenseBmp::GetVert(UINT ids)
// Same as GetLoc but scaled to the current screen hight of the bitmap
{
UINT ui = GetLoc(ids);
LONG h = ScreenHeight();
return ui * h / GetLoc(IDS_LOC_MAX);
}
void CLicenseBmp::InitializeText()
{
TCHAR szIsPub[128];
TCHAR szUnderALicense[128];
TCHAR szEndorsements[128];
//
// Load the string and the font that we use as a watermark on the bitmap
// in the 'testing' case
//
{
m_ulTestingBanterSize = GetLoc(IDS_TESTSIZE); // in tenths of points
m_lTestingBanterOrientation = GetLoc(IDS_TESTORIENT); // in tenths of degree
::LoadString(Hinst(), IDS_TESTINGBANTER, (LPTSTR)m_szTestingBanter, 48);
::LoadString(Hinst(), IDS_FONTNAME, &m_szFontName[0], 128);
m_ulFontPitchAndFamily = GetLoc(IDS_FONTPITCHANDFAMILY);
m_hlinkHeight = (int)GetLoc(IDS_HLINKHEIGHT);
m_banterHeight = (int)GetLoc(IDS_BANTERHEIGHT);
LOGFONT lf;
memset(&lf, 0, sizeof(lf));
lf.lfCharSet = GetLoc(IDS_CHARSET);
lf.lfEscapement = m_lTestingBanterOrientation;
lf.lfOrientation = lf.lfEscapement; // Win95/WinNT compatibility issue?
lf.lfHeight = m_ulTestingBanterSize;
lf.lfWeight = FW_BOLD;
lf.lfPitchAndFamily = PitchAndFamily();
_tcscpy(lf.lfFaceName, &m_szFontName[0]);
// Convert the point size to logical units for the screen
{
HDC hDC = ::GetDC(NULL);
POINT pt;
pt.y = ::GetDeviceCaps(hDC, LOGPIXELSY) * lf.lfHeight;
pt.y /= 720; // 72 points/inch, 10 decipoints/point
::DPtoLP(hDC, &pt, 1);
lf.lfHeight = -pt.y;
::ReleaseDC(NULL, hDC);
}
m_hfontTestingBanter = ::CreateFontIndirect(&lf);
}
//
// Setup the various strings that displayed in the dialog proper
//
UINT idsUnder;
BOOL fTestingOnly = m_pdlg->FTestingOnly();
if (fTestingOnly)
{
idsUnder = m_pdlg->FCommercial() ? IDS_UNDERTESTINGCOMMERCIAL : IDS_UNDERTESTINGINDIVIDUAL;
}
else
{
idsUnder = m_pdlg->FCommercial() ? IDS_UNDERCOMMERCIAL : IDS_UNDERINDIVIDUAL;
}
::LoadString(Hinst(), IDS_ISPUBLISHEDBY, (LPTSTR)szIsPub, 128);
::LoadString(Hinst(), idsUnder, (LPTSTR)szUnderALicense, 128);
::LoadString(Hinst(), IDS_ENDORSEMENTS, (LPTSTR)szEndorsements, 128);
m_name. Initialize(m_pdlg->ProgramName(), m_pdlg->FLinkProgram(), FALSE, FALSE, this, GetVert(IDS_LOC_OPUS));
m_ispub. Initialize(szIsPub, FALSE, TRUE, FALSE, this, GetVert(IDS_LOC_ISPUBLISHEDBY));
m_publisher.Initialize(m_pdlg->Publisher(), FALSE, FALSE, FALSE, this, GetVert(IDS_LOC_PUBLISHER));
m_undera. Initialize(szUnderALicense, FALSE, TRUE, fTestingOnly, this, GetVert(IDS_LOC_UNDERCREDENTIALS));
m_agency. MultiLine(TRUE);
m_agency. Initialize(m_pdlg->Agency(), m_pdlg->FLinkAgency(), FALSE, FALSE, this, GetVert(IDS_LOC_AGENCY));
m_fHasEndorsements = m_pdlg->FHasEndorsements();
if (m_fHasEndorsements)
{
m_endorse.Left();
m_endorse.Initialize(szEndorsements, TRUE, FALSE, FALSE, this, GetVert(IDS_LOC_EXPIRES));
}
FILETIME ft = m_pdlg->ExpirationDate();
LPTSTR szExpire[128];
if (ft.dwLowDateTime == 0 && ft.dwHighDateTime == 0)
{ // No expiration
szExpire[0] = '\0';
}
else
{
// Why do we show the date value only? Because the date originates from
// a value stored in UTC, which may, for example, have been created in a different
// time zone than you are in now, and so won't appear, in local time (which we want
// to show) to be a whole day. Note that the actual expiration test carried out
// uses the whole time and date value.
//
SYSTEMTIME st;
FileTimeToSystemTime(&ft, &st);
st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
TCHAR szDate[128];
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, szDate, 128);
FormatMessage(Hinst(), (LPTSTR)szExpire, 128, IDS_EXPIRES, (LPCTSTR)szDate);
}
if (m_fHasEndorsements)
{
m_expiration.Right();
}
else
{
m_expiration.Center();
}
m_expiration.Initialize((LPTSTR)szExpire, FALSE, FALSE, FALSE, this, GetVert(IDS_LOC_EXPIRES));
m_name .SetRrn(RRN_CLICKED_PROGRAMINFO);
m_agency .SetRrn(RRN_CLICKED_AGENCYINFO);
m_endorse.SetRrn(RRN_CLICKED_ENDORSEMENTS);
}
void CLicenseBmp::InitializeBmp()
{
m_hbmp = LoadResourceBitmap(Hinst(), MAKEINTRESOURCE(IDB_LICENSE), &m_hpal);
m_bmpSeal = LoadResourceBitmap(Hinst(), MAKEINTRESOURCE(IDB_SEAL), NULL);
}
void CLicenseBmp::InitializeToolTip()
{
m_hwndToolTip = CreateWindow
(
TOOLTIPS_CLASS, (LPSTR) NULL, TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, GetWindow(), (HMENU) NULL, Hinst(), NULL
);
//
// No need to destroy this in our destructor because we are the parent window
//
if (m_hwndToolTip != NULL)
{
m_name .InitializeToolTip(m_hwndToolTip);
m_agency .InitializeToolTip(m_hwndToolTip);
m_endorse .InitializeToolTip(m_hwndToolTip);
}
}
void CLicenseBmp::Initialize()
{
if (!m_fInitialized)
{
InitCommonControls();
InitializeText();
InitializeBmp();
InitializeToolTip();
m_fInitialized = TRUE;
}
}
HRESULT CLicenseBmp::GetToolTipText(RRN rrn, LPOLESTR* pwsz)
{
return m_pdlg->GetToolTipText(rrn, pwsz);
}
/////////////////////////////////////////////////////////////////////////////
// CLicenseBmp message handlers
void CLicenseBmp::RelayMessage(LPMSG pmsg)
{
//
// Relay it to the tool tip control
//
if (m_hwndToolTip)
{
SendMessage(m_hwndToolTip, TTM_RELAYEVENT, 0, (LPARAM)pmsg);
}
}
void CLicenseBmp::OnLButtonDown(UINT nFlags, POINT& point)
// If the user clicks on one of the hyperlinks, dismiss the dialog and go away
{
RRN rrn = HitTest(point);
if (rrn != RRN_NO)
{
m_pdlg->ClickOnLink(rrn);
}
}
void MaskBlt
// Implement our own mask blt to deal with devices that don't support it natively
(
HBITMAP& hbmImage,
HPALETTE hpal,
HDC& hdc, int xDst, int yDst, int dx, int dy
)
{
int xSrc = 0, ySrc = 0;
int xMsk = 0, yMsk = 0;
// Either
// a) I'm not testing for MaskBlt correctly, or
// b) some Win95 cards lie about its support
// For now, we just turn it off and roll our own
if (FALSE) // && (GetDeviceCaps(hdc, RASTERCAPS) & RC_BITBLT))
{
// Device can handle it; let it do it
// Raster opcode 0x00AA0029 == leave destination untouched
//
/* CDC hdcImage;
hdc.CreateCompatibleDC(&hdcImage);
CBitmap* pbmpPrev = hdcImage.SelectObject(&hbmImage);
// We need to create the mask ourselves in any case
// hdc.MaskBlt(xDst,yDst,dx,dy, &hdcImage,xSrc,ySrc, hbmMaskIn,xMsk,yMsk, MAKEROP4(0x00AA0029,SRCCOPY));
hdcImage.SelectObject(pbmpPrev);
*/ }
else
{
// Device can't handle it; we roll our own
//
HDC hdcMask = CreateCompatibleDC(hdc); ASSERT(hdcMask);
HDC hdcMaskInv = CreateCompatibleDC(hdc); ASSERT(hdcMaskInv);
HDC hdcCache = CreateCompatibleDC(hdc); ASSERT(hdcCache);
HDC hdcImage = CreateCompatibleDC(hdc); ASSERT(hdcImage);
HDC hdcImageCrop = CreateCompatibleDC(hdc); ASSERT(hdcImageCrop);
// Create bitmaps
HBITMAP hbmCache = CreateCompatibleBitmap(hdc, dx, dy); ASSERT(hbmCache);
HBITMAP hbmImageCrop = CreateCompatibleBitmap(hdc, dx, dy); ASSERT(hbmImageCrop);
HBITMAP hbmMaskInvert = CreateCompatibleBitmap(hdcMaskInv, dx, dy); ASSERT(hbmMaskInvert);
HBITMAP hbmMask = CreateBitmap(dx, dy, 1, 1, NULL); ASSERT(hbmMask); // B&W bitmap
// Select bitmaps
HBITMAP hbmPrevImage = (HBITMAP)SelectObject(hdcImage, hbmImage); DWORD dw1 = GetLastError();
HBITMAP hbmPrevImageCrop= (HBITMAP)SelectObject(hdcImageCrop, hbmImageCrop); DWORD dw2 = GetLastError();
HBITMAP hbmPrevCache = (HBITMAP)SelectObject(hdcCache, hbmCache); DWORD dw3 = GetLastError();
HBITMAP hbmPrevMask = (HBITMAP)SelectObject(hdcMask, hbmMask); DWORD dw4 = GetLastError();
HBITMAP hbmPrevMaskInv = (HBITMAP)SelectObject(hdcMaskInv, hbmMaskInvert); DWORD dw5 = GetLastError();
ASSERT(hbmPrevMaskInv);
ASSERT(hbmPrevMask);
ASSERT(hbmPrevCache);
ASSERT(hbmPrevImageCrop);
ASSERT(hbmPrevImage);
// Select the palette into each bitmap
HPALETTE hpalCache = SelectPalette(hdcCache, hpal, SELPALMODE);
HPALETTE hpalImage = SelectPalette(hdcImage, hpal, SELPALMODE);
HPALETTE hpalImageCrop = SelectPalette(hdcImageCrop, hpal, SELPALMODE);
HPALETTE hpalMaskInv = SelectPalette(hdcMaskInv, hpal, SELPALMODE);
HPALETTE hpalMask = SelectPalette(hdcMask, hpal, SELPALMODE);
// Create the mask. We want a bitmap which is white (1) where the image is
// rgbTransparent and black (0) where it is another color.
//
// When using BitBlt() to convert a color bitmap to a monochrome bitmap, GDI
// sets to white (1) all pixels that match the background color of the source
// DC. All other bits are set to black (0).
//
COLORREF rgbTransparent = RGB(255,0,255); // this color becomes transparent
COLORREF rgbPrev = SetBkColor(hdcImage, rgbTransparent);
VERIFY(BitBlt(hdcMask, 0,0,dx,dy, hdcImage, 0, 0, SRCCOPY));
SetBkColor(hdcImage, rgbPrev);
// Create the inverted mask
VERIFY(BitBlt(hdcMaskInv, 0,0,dx,dy, hdcMask, xMsk,yMsk, NOTSRCCOPY)); // Sn: Create inverted mask
// Carry out the surgery
VERIFY(BitBlt(hdcCache, 0,0,dx,dy, hdc, xDst,yDst, SRCCOPY)); // S: Get copy of screen
VERIFY(BitBlt(hdcCache, 0,0,dx,dy, hdcMask, 0, 0, SRCAND)); // DSa: zero where new image goes
VERIFY(BitBlt(hdcImageCrop,0,0,dx,dy, hdcImage, xSrc,ySrc, SRCCOPY)); // S: Get copy of image
VERIFY(BitBlt(hdcImageCrop,0,0,dx,dy, hdcMaskInv,0, 0, SRCAND)); // DSa: zero out outside of image
VERIFY(BitBlt(hdcCache, 0,0,dx,dy, hdcImageCrop,0, 0, SRCPAINT)); // DSo: Combine image into cache
VERIFY(BitBlt(hdc, xDst,yDst,dx,dy, hdcCache, 0, 0, SRCCOPY)); // S: Put results back on screen
// VERIFY(BitBlt(hdc, xDst,yDst,dx,dy, hdcCache, 0, 0, SRCCOPY));
// VERIFY(BitBlt(hdc, xDst+dx,yDst,dx,dy, hdcMask, 0, 0, SRCCOPY));
if (hpalCache) SelectPalette(hdcCache, hpalCache, SELPALMODE);
if (hpalImage) SelectPalette(hdcImage, hpalImage, SELPALMODE);
if (hpalImageCrop) SelectPalette(hdcImageCrop, hpalImageCrop, SELPALMODE);
if (hpalMaskInv) SelectPalette(hdcMaskInv, hpalMaskInv, SELPALMODE);
if (hpalMask) SelectPalette(hdcMask, hpalMask, SELPALMODE);
// Tidy up
SelectObject(hdcImage, hbmPrevImage);
SelectObject(hdcImageCrop, hbmPrevImageCrop);
SelectObject(hdcCache, hbmPrevCache);
SelectObject(hdcMask, hbmPrevMask);
SelectObject(hdcMaskInv, hbmPrevMaskInv);
// Free resources
DeleteObject(hbmMaskInvert);
DeleteObject(hbmMask);
DeleteObject(hbmImageCrop);
DeleteObject(hbmCache);
// Delete DCs
DeleteDC(hdcMask);
DeleteDC(hdcMaskInv);
DeleteDC(hdcCache);
DeleteDC(hdcImage);
DeleteDC(hdcImageCrop);
}
}
int CLicenseBmp::OnQueryNewPalette()
{
HDC hDC = GetDC(GetWindow());
HPALETTE hOldPal = SelectPalette(hDC, m_hpal, SELPALMODE);
int iTemp = RealizePalette(hDC); // Realize drawing palette.
SelectPalette(hDC, hOldPal, TRUE);
RealizePalette(hDC);
ReleaseDC(GetWindow(), hDC);
//
// Did the realization change?
//
if (iTemp)
{
InvalidateRect(GetWindow(), NULL, FALSE);
}
return(iTemp);
}
LONG CLicenseBmp::ScreenHeight()
//
// Answer the height of the bitmap, in pixels, on the screen
//
{
RECT rc;
::GetClientRect(GetWindow(), &rc);
return Height(rc);
}
void CLicenseBmp::OnPaint()
{
Initialize();
#ifdef _DEBUG
OutputDebugString("paint\n");
#endif
// Draw the license bitmap
/* BLOCK */
{
PAINTSTRUCT ps;
// VERIFY(UnrealizeObject(m_hpal));
HDC hdc = BeginPaint(GetWindow(), &ps);
HPALETTE hpalPrevHdc = SelectPalette(hdc,m_hpal,SELPALMODE);
RealizePalette(hdc);
BITMAP bm;
BITMAP bmLicense;
BITMAP bmSeal;
BITMAP bmLogo;
// Draw the background license bitmap
/* BLOCK */
{
::GetObject(m_hbmp, sizeof(BITMAP), (LPSTR)&bm);
bmLicense = bm;
HDC hdcMem = CreateCompatibleDC(hdc);
HPALETTE hpalPrevHdcMem = SelectPalette(hdcMem,m_hpal,SELPALMODE);
// The licence background bitmap is optimized for VGA-sized dialog units,
// but we need to make it function for other sizes as well.
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hdcMem, m_hbmp);
RECT rc;
::GetClientRect(GetWindow(), &rc);
if (Width(rc) == bm.bmWidth && Height(rc) == bm.bmHeight)
{
::BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hdcMem,0,0,SRCCOPY);
}
else
{
::StretchBlt(hdc,0,0,Width(rc),Height(rc),hdcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
}
::SelectObject(hdcMem,hOldBitmap);
if (hpalPrevHdcMem) SelectPalette(hdcMem, hpalPrevHdcMem, SELPALMODE);
DeleteDC(hdcMem);
}
// In the testing case, draw the background watermark
if (m_pdlg->FTestingOnly() && m_hfontTestingBanter)
{
::SetBkMode(hdc, TRANSPARENT);
HFONT hfontPrev = (HFONT)::SelectObject(hdc, m_hfontTestingBanter);
::SetTextColor(hdc, RGB(196,196,196)); // set the color of the watermark text
::SetTextAlign(hdc, TA_BASELINE | TA_CENTER);
int cch = _tcslen(m_szTestingBanter);
RECT rc; ::GetClientRect(GetWindow(), &rc); // get the bitmap location
SIZE size; ::GetTextExtentPoint32(hdc, m_szTestingBanter, cch, &size);
::TextOut(hdc, (Width(rc))/2, Height(rc) - (Height(rc)-size.cy)/2, m_szTestingBanter, cch);
::SelectObject(hdc, hfontPrev);
}
// Draw the seal
memset(&bmSeal, 0, sizeof(bmSeal));
int ySeal = 26;
int xSeal = 29;
if (m_pdlg->FIncludeSeal())
{
::GetObject(m_bmpSeal, sizeof(BITMAP), (LPSTR)&bmSeal);
// palette already set in hdc from above
MaskBlt(m_bmpSeal, m_hpal, hdc, xSeal,ySeal,bmSeal.bmWidth,bmSeal.bmHeight);
}
// Draw the agency logo
HBITMAP hbmp = m_pdlg->AgencyLogo();
if (hbmp)
{
// Get the information about the logo
::GetObject(hbmp, sizeof(BITMAP), (LPSTR)&bmLogo);
// Center the logo in the space to the right of the seal
int xSealRight = xSeal + bmSeal.bmWidth;
int x = xSealRight + (bmLicense.bmWidth - xSealRight - bmLogo.bmWidth) / 2;
int y = ySeal;
MaskBlt(hbmp, m_hpal, hdc, x, y, bmLogo.bmWidth, bmLogo.bmHeight);
}
if (hpalPrevHdc)
{
SelectPalette(hdc,hpalPrevHdc,SELPALMODE);
RealizePalette(hdc);
}
::EndPaint(GetWindow(), &ps);
}
// Draw the text on top of the license
//
// REVIEW: speed improvements possible here
//
m_name.Draw();
m_ispub.Draw();
m_publisher.Draw();
m_undera.Draw();
m_agency.Draw();
if (m_fHasEndorsements)
m_endorse.Draw();
m_expiration.Draw();
}
RRN CLicenseBmp::HitTest(POINT& pt)
// pt is in our client coordinate space
{
if (m_name.HitTest(pt))
return m_name.GetRrn();
if (m_agency.HitTest(pt))
return m_agency.GetRrn();
if (m_endorse.HitTest(pt))
return m_endorse.GetRrn();
return RRN_NO;
}
/////////////////////////////////////////////////////////////////////////////
// Hyperlink helper class for CLicenseBmp
CHyperLink::CHyperLink()
{
m_fActive = FALSE;
m_pLicense = NULL;
m_fBanter = FALSE;
m_fTesting = FALSE;
m_font = NULL;
m_pLicense = NULL;
m_sz[0] = 0;
m_alignment = 0;
m_rrn = RRN_NO;
MultiLine(FALSE);
Center();
}
CHyperLink::~CHyperLink()
{
if (m_font)
{
DeleteObject(m_font);
}
}
void CHyperLink::Initialize(
LPCTSTR sz,
BOOL fActive,
BOOL fBanter,
BOOL fTesting,
CLicenseBmp* pLicense,
int dy)
{
_tcscpy(m_sz, sz);
m_fActive = fActive;
m_pLicense = pLicense;
m_fBanter = fBanter;
m_fTesting = fTesting;
SetFont();
CalcLocation(dy);
}
void CHyperLink::SetFont()
// Set the font according to whether this is a hyperlink or not
{
LOGFONT lf;
memset(&lf, 0, sizeof(lf));
lf.lfCharSet = m_pLicense->GetLoc(IDS_CHARSET);
lf.lfHeight = m_pLicense->HlinkHeight(); // 10 points
if (m_fActive)
{
lf.lfUnderline = TRUE;
lf.lfWeight = FW_BOLD; // bold
}
else
{
lf.lfWeight = FW_BOLD; // normal
}
if (m_fBanter) // used for, eg., 'is published by' and 'under credentials issued by'
{
lf.lfItalic = TRUE;
lf.lfHeight = m_pLicense->BanterHeight(); // 8.5 points
lf.lfWeight = FW_NORMAL;
lf.lfPitchAndFamily = m_pLicense->PitchAndFamily();
_tcscpy(lf.lfFaceName, m_pLicense->FontName());
}
else
{
lf.lfPitchAndFamily = m_pLicense->PitchAndFamily();
_tcscpy(lf.lfFaceName, m_pLicense->FontName());
}
// Convert the point size to logical units for the screen
{
HDC hDC = ::GetDC(NULL);
POINT pt;
pt.y = ::GetDeviceCaps(hDC, LOGPIXELSY) * lf.lfHeight;
pt.y /= 720; // 72 points/inch, 10 decipoints/point
::DPtoLP(hDC, &pt, 1);
lf.lfHeight = -pt.y;
::ReleaseDC(NULL, hDC);
}
m_font = ::CreateFontIndirect(&lf);
}
HWND CHyperLink::Window()
{
return GetDlgItem(GetParent(m_pLicense->GetWindow()), IDC_LICENSEINSET);
}
void CHyperLink::CalcLocation(int dy)
//
// Calculate the rectangle we occupy on the screen, setting that in our inst variable.
//
{
RECT rcLic, rcBmp;
::GetWindowRect(m_pLicense->GetWindow(), &rcBmp); // coordinate origin
::GetWindowRect(Window(), &rcLic); // gives size limits, offset
// BLOCK
{
HDC hdc = GetDC(NULL);
HFONT hfontPrev = (HFONT)::SelectObject(hdc, m_font);
m_rc = rcLic;
m_rc.bottom =
m_rc.top +
::DrawText(hdc, m_sz, _tcslen(m_sz), &m_rc, DT_CALCRECT | DrawFlags());
// DrawText returns height
::SelectObject(hdc, hfontPrev);
::ReleaseDC(NULL, hdc);
}
LONG dx = rcLic.left - rcBmp.left;
LONG w = Width(m_rc);
LONG h = Height(m_rc);
m_rc.bottom = dy + h;
m_rc.top = dy;
switch (m_alignment)
{
case DT_CENTER:
m_rc.left = dx + (Width(rcLic)-w) / 2;
m_rc.right = m_rc.left + w;
break;
case DT_LEFT:
m_rc.left = dx;
m_rc.right = m_rc.left + w;
break;
case DT_RIGHT:
m_rc.right = dx + Width(rcLic);
m_rc.left = m_rc.right - w;
break;
}
}
void CHyperLink::InitializeToolTip(HWND hwndTT)
//
// If we have a target, then setup ourselves in the tool tip
//
{
LPWSTR wsz;
if (m_fActive && SUCCEEDED(m_pLicense->GetToolTipText(m_rrn, &wsz)))
{
TOOLINFO ti;
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = 0;
ti.hwnd = m_pLicense->GetWindow();
ti.hinst = m_pLicense->Hinst();
ti.rect = m_rc;
ti.uId = (UINT) 0; // we don't need this
TCHAR sz[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, wsz, -1, &sz[0], MAX_PATH, NULL, NULL);
ti.lpszText = &sz[0];
SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
CoTaskMemFree(wsz);
}
}
void CHyperLink::Draw()
// Draw this link on the screen
{
HWND hwnd = m_pLicense->GetWindow();
HDC hdc = ::GetWindowDC(hwnd);
int wSave = ::SaveDC(hdc);
//
// Set the font and transparency
//
::SelectObject(hdc, m_font);
SetBkMode(hdc, TRANSPARENT);
//
// Set the text color
//
if (m_fTesting)
::SetTextColor(hdc, RGB(255,0,0)); // red in testing case
else if (m_fActive)
::SetTextColor(hdc, RGB(0,0,255)); // blue for hyperlinks
else if (m_fBanter)
::SetTextColor(hdc, RGB(64,64,64)); // gray for banter
else
::SetTextColor(hdc, RGB(0,0,0)); // black for non-links
//
// Draw the text
//
::DrawText(hdc, m_sz, _tcslen(m_sz), &m_rc, DrawFlags());
//
// Clean up
//
::RestoreDC(hdc, wSave);
::ReleaseDC(hwnd, hdc);
}
BOOL CHyperLink::HitTest(POINT& pt)
// Answer true if the indicated point is inside our rectangle. The
// point must be in our client coordinate space
{
if (m_fActive)
return PtInRect(&m_rc, pt);
else
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Utilities
HPALETTE CreateDIBPalette (LPBITMAPINFO lpbmi, LPINT lpiNumColors);
HBITMAP LoadResourceBitmap(HINSTANCE hInstance, LPSTR lpString, HPALETTE* lphPalette)
// Load the indicated bitmap resource and its palette. To free the
// bitmap, use DeleteObject
// palette, use DeleteObject
{
HRSRC hRsrc;
HGLOBAL hGlobal;
HBITMAP hBitmapFinal = NULL;
LPBITMAPINFOHEADER lpbi;
HDC hdc;
int iNumColors;
if (hRsrc = ::FindResource(hInstance, lpString, RT_BITMAP))
{
hGlobal = ::LoadResource(hInstance, hRsrc);
lpbi = (LPBITMAPINFOHEADER)::LockResource(hGlobal);
hdc = GetDC(NULL);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmMem = CreateCompatibleBitmap(hdc, 10, 10); ASSERT(hbmMem);
HBITMAP hbmPrev = (HBITMAP)SelectObject(hdcMem, hbmMem);
HPALETTE hpal = CreateDIBPalette((LPBITMAPINFO)lpbi, &iNumColors);
HPALETTE hpalPrev = NULL;
if (hpal)
{
hpalPrev = SelectPalette(hdcMem,hpal,FALSE);
RealizePalette(hdcMem);
}
hBitmapFinal = ::CreateDIBitmap(hdcMem,
(LPBITMAPINFOHEADER)lpbi,
(LONG)CBM_INIT,
(LPSTR)lpbi + lpbi->biSize + iNumColors * sizeof(RGBQUAD),
(LPBITMAPINFO)lpbi,
DIB_RGB_COLORS );
if (hpalPrev)
{
SelectPalette(hdcMem, hpalPrev, FALSE);
RealizePalette(hdcMem);
}
if (lphPalette)
{
// Let the caller own this if he asked for it
*lphPalette = hpal;
}
else
{
// We don't need it any more
::DeleteObject(hpal);
}
// Tidy up
SelectObject(hdcMem, hbmPrev);
DeleteObject(hbmMem);
DeleteDC(hdcMem);
ReleaseDC(NULL,hdc);
UnlockResource(hGlobal);
FreeResource(hGlobal);
}
return (hBitmapFinal);
}
HPALETTE CreateDIBPalette (LPBITMAPINFO lpbmi, LPINT lpiNumColors)
// Create and return a palette from the info in a DIB bitmap.
// To free the returned palette, use DeleteObject.
{
LPBITMAPINFOHEADER lpbi;
LPLOGPALETTE lpPal;
HANDLE hLogPal;
HPALETTE hPal = NULL;
int i;
lpbi = (LPBITMAPINFOHEADER)lpbmi;
if (lpbi->biBitCount <= 8)
{
if (lpbi->biClrUsed == 0)
*lpiNumColors = (1 << lpbi->biBitCount);
else
*lpiNumColors = lpbi->biClrUsed;
}
else
*lpiNumColors = 0; // No palette needed for 24 BPP DIB
if (*lpiNumColors)
{
hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) + sizeof (PALETTEENTRY) * (*lpiNumColors));
lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);
lpPal->palVersion = 0x300;
lpPal->palNumEntries = *lpiNumColors;
for (i = 0; i < *lpiNumColors; i++)
{
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
hPal = CreatePalette(lpPal);
GlobalUnlock (hLogPal);
GlobalFree (hLogPal);
}
return hPal;
}
/////////////////////////////////////////////////////////////////////////////////////////
HINSTANCE CLicenseBmp::Hinst()
{
return m_pdlg->Hinst();
}
void CLicenseBmp::DoSubclass()
{
m_prevProc = (WNDPROC)SetWindowLong(GetWindow(), GWL_WNDPROC, (LONG)CLicenseBmpProc);
//
// Set 'no class cursor' so that SetCursor will work.
//
m_prevCursor = (HCURSOR)SetClassLong(GetWindow(), GCL_HCURSOR, NULL);
}
void CLicenseBmp::DoUnsubclass()
{
SetWindowLong(GetWindow(), GWL_WNDPROC, (LONG)m_prevProc);
SetWindowLong(GetWindow(), GCL_HCURSOR, (LONG)m_prevCursor);
m_prevProc = NULL;
}
LRESULT APIENTRY CLicenseBmpProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
//
// This is the dialog proc for the license bitmap
//
{
CLicenseBmp* This = (CLicenseBmp*)GetWindowLong(hwnd, GWL_USERDATA);
switch (uMsg)
{
case WM_HELP:
{
// Define an array of dword pairs,
// where the first of each pair is the control ID,
// and the second is the context ID for a help topic,
// which is used in the help file.
static const DWORD aMenuHelpIDs[] =
{
IDC_LICENSEBMP, 2,
0, 0
};
LPHELPINFO lphi;
lphi = (LPHELPINFO)lParam;
if (lphi->iContextType == HELPINFO_WINDOW) // must be for a control
{
WinHelp
(
(HWND)(lphi->hItemHandle),
"WINTRUST.HLP",
HELP_WM_HELP,
(DWORD)(LPVOID)aMenuHelpIDs
);
}
return TRUE;
}
case WM_PAINT:
This->OnPaint();
break;
case WM_LBUTTONDOWN:
{
UINT nFlags = wParam;
POINT pt;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
This->OnLButtonDown(nFlags, pt);
//
// Fall through!
//
}
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
{
MSG msg;
msg.hwnd = hwnd;
msg.message = uMsg;
msg.wParam = wParam;
msg.lParam = lParam;
msg.time = GetMessageTime();
DWORD dw = GetMessagePos();
msg.pt.x = LOWORD(dw);
msg.pt.y = HIWORD(dw);
This->RelayMessage(&msg);
break;
}
default:
return CallWindowProc((WNDPROC)(This->m_prevProc), hwnd, uMsg, wParam, lParam);
}
return 0;
}
HWND CLicenseBmp::GetWindow()
{
return m_hWnd;
}
void CLicenseBmp::SetWindow(HWND hwnd)
{
m_hWnd = hwnd;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)this);
}