You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
968 lines
28 KiB
968 lines
28 KiB
#include "precomp.h"
|
|
#include "adjustui.h"
|
|
|
|
#pragma warning(disable: 4244) // disable loss of data warning since we do so
|
|
// much casting in this file
|
|
#pragma pack(push, 2)
|
|
typedef struct tagDLGTEMPLATEEX {
|
|
WORD dlgVer;
|
|
WORD signature;
|
|
DWORD helpID;
|
|
DWORD exStyle;
|
|
DWORD style;
|
|
WORD cDlgItems;
|
|
short x;
|
|
short y;
|
|
short cx;
|
|
short cy;
|
|
} DLGTEMPLATEEX, *PDLGTEMPLATEEX;
|
|
typedef const DLGTEMPLATEEX* PCDLGTEMPLATEEX;
|
|
|
|
typedef struct {
|
|
DWORD helpID;
|
|
DWORD exStyle;
|
|
DWORD style;
|
|
short x;
|
|
short y;
|
|
short cx;
|
|
short cy;
|
|
WORD id;
|
|
WORD reserved;
|
|
} DLGITEMTEMPLATEEX, *PDLGITEMTEMPLATEEX;
|
|
typedef const DLGITEMTEMPLATEEX* PCDLGITEMTEMPLATEEX;
|
|
#pragma pack(pop)
|
|
|
|
// globals for banner
|
|
HBITMAP g_hBannerBmp = NULL;
|
|
HFONT g_hFont = NULL;
|
|
|
|
static HWND s_hBannerWnd = NULL;
|
|
static WNDPROC s_lpfnBannerTextCtrlProc = NULL;
|
|
static HWND s_hBannerText = NULL;
|
|
TCHAR s_szBannerText[MAX_PATH];
|
|
static WNDPROC s_lpfnPSWndProc = NULL;
|
|
|
|
|
|
// PrepareDlgTemplate and ChangeDlgTemplateFont helpers
|
|
BOOL getBitmapDimensions(HINSTANCE hinstBmp, UINT nID, PSIZE psizeBmp);
|
|
BOOL mapPixelsToDlgUnits(const LOGFONT *plf, PSIZE psize);
|
|
BOOL createStaticControl(PCSTATICCTRL pCtrl, BOOL fEx, PVOID *ppvDIT, PDWORD pcbDIT);
|
|
HRESULT getDlgTemplateSize(LPCVOID pvDlg, LPDWORD pcbDlg);
|
|
BOOL loadDialogTemplate (HINSTANCE hinstDlg, UINT nID, PVOID *ppvDT, PDWORD pcbDT);
|
|
|
|
PBYTE skipDlgString(PBYTE pb);
|
|
PBYTE alignDWORD(PBYTE pb);
|
|
|
|
// IsTahomaFontExist helpers
|
|
int CALLBACK enumFontFamExProc(ENUMLOGFONTEX *, NEWTEXTMETRICEX *, int, LPARAM lParam);
|
|
|
|
// PropSheetProc helpers
|
|
void initializeBannerTextCtrlFont(HWND hWnd, INT nId);
|
|
BOOL CALLBACK bannerTextCtrlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
void paintBmpInHdcRect(HBITMAP hBmp, HDC hDC, RECT rect);
|
|
void handleEraseBkgndMsg(HWND hDlg, HDC hDC);
|
|
BOOL CALLBACK propertySheetWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
|
|
|
|
HRESULT PrepareDlgTemplate(PCMODIFYDLGTEMPLATE pmdt, LPCVOID pvDlg, PVOID *ppvDT, LPDWORD pcbDlg)
|
|
{
|
|
LOGFONT lf;
|
|
SIZE sizeBmpOffset;
|
|
PCDLGTEMPLATEEX pdt2;
|
|
LPCDLGTEMPLATE pdt; // for some weird reason there is no PCDLGTEMPLATE
|
|
PDLGITEMTEMPLATEEX pdit2;
|
|
PDLGITEMTEMPLATE pdit;
|
|
PBYTE pb;
|
|
HRESULT hr;
|
|
DWORD cbDlg;
|
|
WORD cDlgItems,
|
|
cbCreateParams;
|
|
BOOL fEx,
|
|
fResult;
|
|
|
|
USES_CONVERSION;
|
|
|
|
//----- Initialization and parameter validation -----
|
|
if (pmdt == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (pmdt->hinst == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (pmdt->scBmpCtrl.nCtrlType == CTRL_BITMAP && pmdt->scBmpCtrl.nID == 0)
|
|
return E_INVALIDARG;
|
|
|
|
if (pvDlg == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (ppvDT == NULL)
|
|
return E_POINTER;
|
|
*ppvDT = NULL;
|
|
|
|
if (pcbDlg == NULL)
|
|
return E_INVALIDARG;
|
|
*pcbDlg = 0;
|
|
|
|
hr = getDlgTemplateSize(pvDlg, &cbDlg);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
ZeroMemory(&lf, sizeof(lf));
|
|
|
|
//----- Resource allocation -----
|
|
*ppvDT = CoTaskMemAlloc(cbDlg * 2);
|
|
if (*ppvDT == NULL)
|
|
return E_OUTOFMEMORY;
|
|
ZeroMemory(*ppvDT, cbDlg * 2);
|
|
hr = S_OK;
|
|
|
|
//----- Parse through Dialog Template -----
|
|
UINT nStyleOffset, nDlgItemsOffset,
|
|
nWidthOffset, nHeightOffset;
|
|
|
|
pdt = NULL;
|
|
pdt2 = (PCDLGTEMPLATEEX)pvDlg; // assume extended style
|
|
|
|
if (pdt2->signature == 0xFFFF) {
|
|
if (pdt2->dlgVer != 1)
|
|
return E_UNEXPECTED; // Chicago sanity check
|
|
|
|
nStyleOffset = (PBYTE)&pdt2->style - (PBYTE)pdt2;
|
|
nDlgItemsOffset = (PBYTE)&pdt2->cDlgItems - (PBYTE)pdt2;
|
|
nWidthOffset = (PBYTE)&pdt2->cx - (PBYTE)pdt2;
|
|
nHeightOffset = (PBYTE)&pdt2->cy - (PBYTE)pdt2;
|
|
|
|
pb = (PBYTE)(pdt2 + 1);
|
|
fEx = TRUE;
|
|
}
|
|
else {
|
|
pdt = (LPCDLGTEMPLATE)pvDlg;
|
|
pdt2 = NULL;
|
|
|
|
nStyleOffset = (PBYTE)&pdt->style - (PBYTE)pdt;
|
|
nDlgItemsOffset = (PBYTE)&pdt->cdit - (PBYTE)pdt;
|
|
nWidthOffset = (PBYTE)&pdt->cx - (PBYTE)pdt;
|
|
nHeightOffset = (PBYTE)&pdt->cy - (PBYTE)pdt;
|
|
|
|
pb = (PBYTE)(pdt + 1);
|
|
fEx = FALSE;
|
|
}
|
|
|
|
// skip over menu, window class and window text
|
|
pb = skipDlgString(pb);
|
|
pb = skipDlgString(pb);
|
|
pb = skipDlgString(pb);
|
|
|
|
// skip over font info: point size and typeface name
|
|
if (((*(PDWORD)((PBYTE)pvDlg + nStyleOffset)) & DS_SETFONT) != 0) {
|
|
if (fEx) {
|
|
lf.lfHeight = *(PWORD)pb; pb += sizeof(WORD);
|
|
lf.lfWeight = *(PWORD)pb; pb += sizeof(WORD);
|
|
lf.lfItalic = (BYTE)*(PWORD)pb; pb += sizeof(WORD);
|
|
}
|
|
else {
|
|
lf.lfHeight = *(PWORD)pb; pb += sizeof(WORD);
|
|
}
|
|
|
|
StrCpyN(lf.lfFaceName, W2CT((LPCWSTR)pb), LF_FACESIZE);
|
|
pb = skipDlgString(pb);
|
|
}
|
|
|
|
// finally, adjust to DWORD boundary
|
|
pb = alignDWORD(pb);
|
|
|
|
//----- Make new sence out of Dialog Template -----
|
|
SIZE sizeIncrease;
|
|
DWORD cbDlgTemplate;
|
|
|
|
cbDlgTemplate = pb - (PBYTE)pvDlg;
|
|
CopyMemory(*ppvDT, pvDlg, cbDlgTemplate);
|
|
|
|
fResult = getBitmapDimensions(pmdt->hinst, pmdt->scBmpCtrl.nID, &sizeBmpOffset);
|
|
if (!fResult) {
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
// ok, they are in dialog units now, kinda, really ;-)
|
|
fResult = mapPixelsToDlgUnits(&lf, &sizeBmpOffset);
|
|
if (!fResult) {
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
sizeIncrease.cx = sizeIncrease.cy = 0;
|
|
if (pmdt->sizeCtrlsOffset.cx != 0)
|
|
sizeIncrease.cx = pmdt->scBmpCtrl.rect.left + sizeBmpOffset.cx + pmdt->sizeCtrlsOffset.cx;
|
|
|
|
if (pmdt->sizeCtrlsOffset.cy != 0)
|
|
sizeIncrease.cy = pmdt->scBmpCtrl.rect.top + sizeBmpOffset.cy + pmdt->sizeCtrlsOffset.cy;
|
|
|
|
*(PWORD)((PBYTE)*ppvDT + nDlgItemsOffset) += 2;
|
|
*(PWORD)((PBYTE)*ppvDT + nWidthOffset) += (WORD)sizeIncrease.cx;
|
|
*(PWORD)((PBYTE)*ppvDT + nHeightOffset) += (WORD)sizeIncrease.cy;
|
|
|
|
//----- Add control with the bitmap -----
|
|
PVOID pvCtrl;
|
|
DWORD cbCtrl;
|
|
DWORD cbCtrlsOffset;
|
|
|
|
fResult = createStaticControl(&pmdt->scBmpCtrl, fEx, &pvCtrl, &cbCtrl);
|
|
if (!fResult) {
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
CopyMemory((PBYTE)*ppvDT + cbDlgTemplate, pvCtrl, cbCtrl);
|
|
cbCtrlsOffset = cbCtrl;
|
|
|
|
ASSERT(pvCtrl != NULL);
|
|
CoTaskMemFree(pvCtrl);
|
|
|
|
//----- Add static text control -----
|
|
STATICCTRL scTextCtrl;
|
|
|
|
scTextCtrl = pmdt->scTextCtrl;
|
|
scTextCtrl.rect.left = 7;
|
|
scTextCtrl.rect.top = (sizeBmpOffset.cy / 2) - 11;
|
|
scTextCtrl.rect.right = sizeBmpOffset.cx - 7;
|
|
scTextCtrl.rect.bottom = scTextCtrl.rect.top + 18;
|
|
|
|
fResult = createStaticControl(&scTextCtrl, fEx, &pvCtrl, &cbCtrl);
|
|
if (!fResult) {
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
CopyMemory((PBYTE)*ppvDT + cbDlgTemplate + cbCtrlsOffset, pvCtrl, cbCtrl);
|
|
cbCtrlsOffset += cbCtrl;
|
|
|
|
ASSERT(pvCtrl != NULL);
|
|
CoTaskMemFree(pvCtrl);
|
|
|
|
//----- Parse through Dialog Item Templates -----
|
|
cDlgItems = *(PWORD)((PBYTE)pvDlg + nDlgItemsOffset);
|
|
if (cDlgItems > 0) {
|
|
ASSERT(cbDlg > cbDlgTemplate);
|
|
CopyMemory((PBYTE)*ppvDT + cbDlgTemplate + cbCtrlsOffset, pb, cbDlg - cbDlgTemplate);
|
|
pb = (PBYTE)*ppvDT + cbDlgTemplate + cbCtrlsOffset;
|
|
|
|
while (cDlgItems-- > 0) {
|
|
pdit = NULL; pdit2 = NULL;
|
|
if (fEx) {
|
|
pdit2 = (PDLGITEMTEMPLATEEX)pb;
|
|
|
|
if (pmdt->sizeCtrlsOffset.cx != 0)
|
|
pdit2->x += (WORD)sizeIncrease.cx;
|
|
|
|
if (pmdt->sizeCtrlsOffset.cy != 0)
|
|
pdit2->y += (WORD)sizeIncrease.cy;
|
|
}
|
|
else {
|
|
pdit = (PDLGITEMTEMPLATE)pb;
|
|
|
|
if (pmdt->sizeCtrlsOffset.cx != 0)
|
|
pdit->x += (WORD)sizeIncrease.cx;
|
|
|
|
if (pmdt->sizeCtrlsOffset.cy != 0)
|
|
pdit->y += (WORD)sizeIncrease.cy;
|
|
}
|
|
|
|
pb += fEx ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE);
|
|
|
|
// skip over window class and window text
|
|
pb = skipDlgString(pb);
|
|
pb = skipDlgString(pb);
|
|
|
|
// skip create parameters
|
|
cbCreateParams = *((PWORD)pb);
|
|
if (fEx)
|
|
pb += sizeof(WORD) + cbCreateParams;
|
|
else
|
|
pb += cbCreateParams > 0 ? cbCreateParams : sizeof(WORD);
|
|
|
|
// point at the next dialog item
|
|
pb = alignDWORD(pb);
|
|
}
|
|
}
|
|
|
|
*pcbDlg = cbDlg + cbCtrlsOffset;
|
|
|
|
Exit:
|
|
if (FAILED(hr)) {
|
|
CoTaskMemFree(*ppvDT);
|
|
*ppvDT = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT SetDlgTemplateFont(HINSTANCE hInst, UINT nDlgID, const LOGFONT *plf, PVOID *ppvDT)
|
|
{
|
|
PCDLGTEMPLATEEX pdt2;
|
|
LPCDLGTEMPLATE pdt; // for some weird reason there is no PCDLGTEMPLATE
|
|
PBYTE pb;
|
|
HRESULT hr;
|
|
PVOID pvDlg;
|
|
DWORD cbDlg;
|
|
BOOL fEx,
|
|
fResult;
|
|
|
|
USES_CONVERSION;
|
|
|
|
//----- Initialization and parameter validation -----
|
|
if (plf == NULL || *plf->lfFaceName == TEXT('\0'))
|
|
return E_INVALIDARG;
|
|
|
|
if (plf->lfHeight == 0)
|
|
return E_INVALIDARG;
|
|
|
|
if (ppvDT == NULL)
|
|
return E_POINTER;
|
|
*ppvDT = NULL;
|
|
|
|
//----- Resource allocation -----
|
|
fResult = loadDialogTemplate(hInst, nDlgID, &pvDlg, &cbDlg);
|
|
if (!fResult)
|
|
return E_FAIL;
|
|
|
|
*ppvDT = CoTaskMemAlloc(cbDlg * 2);
|
|
if (*ppvDT == NULL)
|
|
return E_OUTOFMEMORY;
|
|
ZeroMemory(*ppvDT, cbDlg * 2);
|
|
hr = S_OK;
|
|
|
|
//----- Parse through Dialog Template -----
|
|
PBYTE pbDest;
|
|
DWORD cbSize;
|
|
UINT nStyleOffset;
|
|
|
|
pdt = NULL;
|
|
pdt2 = (PCDLGTEMPLATEEX)pvDlg; // assume extended style
|
|
|
|
if (pdt2->signature == 0xFFFF) {
|
|
if (pdt2->dlgVer != 1)
|
|
return E_UNEXPECTED; // Chicago sanity check
|
|
|
|
nStyleOffset = (PBYTE)&pdt2->style - (PBYTE)pdt2;
|
|
|
|
pb = (PBYTE)(pdt2 + 1);
|
|
fEx = TRUE;
|
|
}
|
|
else {
|
|
pdt = (LPCDLGTEMPLATE)pvDlg;
|
|
pdt2 = NULL;
|
|
|
|
nStyleOffset = (PBYTE)&pdt->style - (PBYTE)pdt;
|
|
|
|
pb = (PBYTE)(pdt + 1);
|
|
fEx = FALSE;
|
|
}
|
|
|
|
// skip over menu, window class and window text
|
|
pb = skipDlgString(pb);
|
|
pb = skipDlgString(pb);
|
|
pb = skipDlgString(pb);
|
|
|
|
cbSize = pb - (PBYTE)pvDlg;
|
|
CopyMemory(*ppvDT, pvDlg, cbSize);
|
|
pbDest = (PBYTE)*ppvDT + cbSize;
|
|
|
|
// change font info: point size and typeface name
|
|
if (((*(PDWORD)((PBYTE)pvDlg + nStyleOffset)) & DS_SETFONT) != 0) {
|
|
UINT nLen;
|
|
|
|
if (fEx) {
|
|
*(PWORD)pbDest = (int)plf->lfHeight;
|
|
pb += 3 * sizeof(WORD);
|
|
pbDest += 3 * sizeof(WORD);
|
|
}
|
|
else {
|
|
*(PWORD)pbDest = (int)plf->lfHeight;
|
|
pb += sizeof(WORD);
|
|
pbDest += sizeof(WORD);
|
|
}
|
|
|
|
nLen = StrLen(plf->lfFaceName);
|
|
|
|
CopyMemory(pbDest, T2CW(plf->lfFaceName), (nLen + 1)*sizeof(WCHAR));
|
|
|
|
pb = skipDlgString(pb); // don't know the length of the old font
|
|
//pbDest += (nLen + 1) * sizeof(WCHAR); // know the length of the new font already
|
|
pbDest = skipDlgString(pbDest);
|
|
}
|
|
|
|
// finally, adjust to DWORD boundary
|
|
pb = alignDWORD(pb);
|
|
pbDest = alignDWORD(pbDest);
|
|
|
|
// copy rest of the template
|
|
CopyMemory(pbDest, pb, cbDlg - (pb - (PBYTE)pvDlg));
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL IsTahomaFontExist(HWND hWnd)
|
|
{
|
|
static fFontExist = FALSE;
|
|
static fFontChecked = FALSE;
|
|
LOGFONT lf;
|
|
HDC hDC;
|
|
|
|
if (!fFontChecked)
|
|
{
|
|
hDC = GetDC(hWnd);
|
|
ZeroMemory(&lf, sizeof(lf));
|
|
lf.lfCharSet = DEFAULT_CHARSET;
|
|
StrCpy(lf.lfFaceName, TEXT("Tahoma"));
|
|
EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)enumFontFamExProc, (LPARAM)&fFontExist, 0);
|
|
ReleaseDC(hWnd, hDC);
|
|
fFontChecked = TRUE;
|
|
}
|
|
return fFontExist;
|
|
}
|
|
|
|
int CALLBACK PropSheetProc(HWND hDlg, UINT uMsg, LPARAM lParam)
|
|
{
|
|
MODIFYDLGTEMPLATE mdt;
|
|
LPVOID pvDlg;
|
|
DWORD cbDlg;
|
|
|
|
if (uMsg == PSCB_PRECREATE)
|
|
{
|
|
ZeroMemory(&mdt, sizeof(mdt));
|
|
|
|
mdt.hinst = g_rvInfo.hInst;
|
|
mdt.sizeCtrlsOffset.cy = -9;
|
|
|
|
// bitmap control parameters
|
|
mdt.scBmpCtrl.nCtrlType = CTRL_BITMAP;
|
|
mdt.scBmpCtrl.nID = IDB_WIZARD;
|
|
mdt.scBmpCtrl.nCtrlID = IDC_BANNERBMPCTRL;
|
|
|
|
// text control parameters
|
|
mdt.scTextCtrl.nCtrlType = CTRL_TEXT;
|
|
mdt.scTextCtrl.nCtrlID = IDC_BANNERTXTCTRL;
|
|
|
|
if (FAILED(PrepareDlgTemplate(&mdt, (LPCVOID)lParam, &pvDlg, &cbDlg)))
|
|
return 1;
|
|
|
|
// replace the old template
|
|
CopyMemory((LPVOID)lParam, pvDlg, cbDlg);
|
|
CoTaskMemFree(pvDlg);
|
|
|
|
// take out the context help button
|
|
|
|
if( lParam )
|
|
{
|
|
DLGTEMPLATE *pDlgTemplate;
|
|
DLGTEMPLATEEX *pDlgTemplateEx;
|
|
|
|
pDlgTemplateEx = (DLGTEMPLATEEX *)lParam;
|
|
if (pDlgTemplateEx->signature == 0xFFFF)
|
|
{
|
|
if (pDlgTemplateEx->dlgVer == 1)
|
|
pDlgTemplateEx->style &= ~DS_CONTEXTHELP;
|
|
}
|
|
else
|
|
{
|
|
pDlgTemplate = (DLGTEMPLATE *)lParam;
|
|
pDlgTemplate->style &= ~DS_CONTEXTHELP;
|
|
}
|
|
}
|
|
}
|
|
else if (uMsg == PSCB_INITIALIZED)
|
|
{
|
|
// BUGBUG: (a-saship) for some reason the bitmap is not loaded within the static control,
|
|
// hence force it to display the bitmap.
|
|
s_hBannerWnd = GetDlgItem(hDlg, IDC_BANNERBMPCTRL);
|
|
if (s_hBannerWnd)
|
|
{
|
|
g_hBannerBmp = LoadBitmap(g_rvInfo.hInst, MAKEINTRESOURCE(IDB_WIZARD));
|
|
if (g_hBannerBmp)
|
|
SendMessage(s_hBannerWnd, STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) g_hBannerBmp);
|
|
}
|
|
|
|
// initialize the text control to set the required font style and subclass it
|
|
// so that it paints itself.
|
|
s_hBannerText = GetDlgItem(hDlg, IDC_BANNERTXTCTRL);
|
|
if (s_hBannerText)
|
|
{
|
|
initializeBannerTextCtrlFont(hDlg, IDC_BANNERTXTCTRL);
|
|
//subclass the text control
|
|
if(s_lpfnBannerTextCtrlProc == NULL)
|
|
s_lpfnBannerTextCtrlProc = (WNDPROC)GetWindowLongPtr(s_hBannerText, GWLP_WNDPROC);
|
|
SetWindowLongPtr(s_hBannerText, GWLP_WNDPROC, (LONG_PTR)bannerTextCtrlProc);
|
|
}
|
|
|
|
// subclass propertysheet window to draw the border and bitmap
|
|
if(s_lpfnPSWndProc == NULL)
|
|
s_lpfnPSWndProc = (WNDPROC)GetWindowLongPtr(hDlg, GWLP_WNDPROC);
|
|
SetWindowLongPtr(hDlg, GWLP_WNDPROC, (LONG_PTR)propertySheetWndProc);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void SetBannerText(HWND hDlg)
|
|
{
|
|
GetWindowText(hDlg, s_szBannerText, countof(s_szBannerText));
|
|
InvalidateRect(s_hBannerWnd, NULL, TRUE);
|
|
InvalidateRect(s_hBannerText, NULL, TRUE);
|
|
}
|
|
|
|
|
|
void ChangeBannerText(HWND hDlg)
|
|
{
|
|
SetWindowText(hDlg, s_szBannerText);
|
|
InvalidateRect(s_hBannerWnd, NULL, TRUE);
|
|
InvalidateRect(s_hBannerText, NULL, TRUE);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Implementation helpers routines (private)
|
|
|
|
//----- PrepareDlgTemplate and ChangeDlgTemplateFont helpers -----
|
|
|
|
BOOL getBitmapDimensions(HINSTANCE hinstBmp, UINT nID, PSIZE psizeBmp)
|
|
{
|
|
BITMAP bm;
|
|
HBITMAP hbmp;
|
|
int iResult;
|
|
|
|
if (hinstBmp == NULL)
|
|
return FALSE;
|
|
|
|
if (psizeBmp == NULL)
|
|
return FALSE;
|
|
psizeBmp->cx = psizeBmp->cy = 0;
|
|
|
|
hbmp = (HBITMAP)LoadImage(hinstBmp, MAKEINTRESOURCE(nID), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_SHARED);
|
|
if (hbmp == NULL)
|
|
return FALSE;
|
|
|
|
iResult = GetObject(hbmp, sizeof(bm), &bm);
|
|
DeleteObject(hbmp);
|
|
|
|
if (iResult == 0)
|
|
return FALSE;
|
|
|
|
psizeBmp->cx = bm.bmWidth;
|
|
psizeBmp->cy = bm.bmHeight;
|
|
return TRUE;
|
|
}
|
|
|
|
// BUGBUG: (andrewgu) Big, big bummer!
|
|
// the limitation to this whole approach is that there is no easy way to convert pixels into
|
|
// dlg units of not yet existent dialog. i looked at the code in user32 and there is way too
|
|
// much stuff to try to duplicate here. for now i'm going to use rude and cruel method of
|
|
// multipling it by 2/3 which is good enough for english systems (no matter big fonts or not).
|
|
// will see if international or accessibility folks complain.
|
|
BOOL mapPixelsToDlgUnits(const LOGFONT *plf, PSIZE psize)
|
|
{
|
|
if (plf == NULL)
|
|
return FALSE;
|
|
|
|
if (psize == NULL)
|
|
return FALSE;
|
|
|
|
psize->cx = MulDiv(psize->cx, 2, 3);
|
|
psize->cy = MulDiv(psize->cy, 2, 3);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL createStaticControl(PCSTATICCTRL pCtrl, BOOL fEx, PVOID *ppvDIT, PDWORD pcbDIT)
|
|
{
|
|
PDLGITEMTEMPLATEEX pdit2;
|
|
PDLGITEMTEMPLATE pdit;
|
|
DWORD dwStyle,
|
|
cbCtrl;
|
|
PBYTE pb;
|
|
|
|
if (pCtrl == NULL)
|
|
return FALSE;
|
|
|
|
if ((pCtrl->nCtrlType != CTRL_BITMAP && pCtrl->nCtrlType != CTRL_TEXT) ||
|
|
(pCtrl->nCtrlType == CTRL_BITMAP && pCtrl->nID == 0))
|
|
return FALSE;
|
|
|
|
if (ppvDIT == NULL)
|
|
return FALSE;
|
|
*ppvDIT = NULL;
|
|
|
|
if (pcbDIT == NULL)
|
|
return FALSE;
|
|
*pcbDIT = 0;
|
|
|
|
// REVIEW: (andrewgu) 4 * sizeof(DWORD) is for the extra stuff
|
|
cbCtrl = sizeof(DLGITEMTEMPLATEEX) + 4 * sizeof(DWORD);
|
|
dwStyle = pCtrl->dwStyle;
|
|
if (dwStyle == 0)
|
|
dwStyle = WS_VISIBLE | WS_CHILD | WS_GROUP;
|
|
|
|
if (pCtrl->nCtrlType == CTRL_BITMAP)
|
|
dwStyle |= SS_BITMAP;
|
|
else if (pCtrl->nCtrlType == CTRL_TEXT)
|
|
dwStyle |= SS_LEFT;
|
|
|
|
*ppvDIT = CoTaskMemAlloc(cbCtrl);
|
|
if (*ppvDIT == NULL)
|
|
return FALSE;
|
|
ZeroMemory(*ppvDIT, cbCtrl);
|
|
|
|
pdit = NULL; pdit2 = NULL;
|
|
if (fEx) {
|
|
pdit2 = (PDLGITEMTEMPLATEEX)*ppvDIT;
|
|
|
|
pdit2->helpID = 0xFFFFFFFF;
|
|
pdit2->exStyle = 0;
|
|
pdit2->style = dwStyle;
|
|
pdit2->x = (short)pCtrl->rect.left;
|
|
pdit2->y = (short)pCtrl->rect.top;
|
|
pdit2->cx = (short)(pCtrl->rect.right - pCtrl->rect.left);
|
|
pdit2->cy = (short)(pCtrl->rect.bottom - pCtrl->rect.top);
|
|
pdit2->id = (short)pCtrl->nCtrlID;
|
|
|
|
pb = (PBYTE)*ppvDIT + sizeof(DLGITEMTEMPLATEEX);
|
|
}
|
|
else {
|
|
pdit = (PDLGITEMTEMPLATE)*ppvDIT;
|
|
|
|
pdit->style = dwStyle;
|
|
pdit->dwExtendedStyle = 0;
|
|
pdit->x = (short)pCtrl->rect.left;
|
|
pdit->y = (short)pCtrl->rect.top;
|
|
pdit->cx = (short)(pCtrl->rect.right - pCtrl->rect.left);
|
|
pdit->cy = (short)(pCtrl->rect.bottom - pCtrl->rect.top);
|
|
pdit->id = (short)pCtrl->nCtrlID;
|
|
|
|
pb = (PBYTE)*ppvDIT + sizeof(DLGITEMTEMPLATE);
|
|
}
|
|
|
|
// class
|
|
*(PWORD)pb = 0xFFFF;
|
|
pb += sizeof(WORD);
|
|
*(PWORD)pb = 0x0082; // static
|
|
pb += sizeof(WORD);
|
|
|
|
// window text
|
|
if(pCtrl->nCtrlType == CTRL_BITMAP) {
|
|
*(PWORD)pb = 0xFFFF;
|
|
pb += sizeof(WORD);
|
|
|
|
*(PWORD)pb = (WORD)pCtrl->nID;
|
|
pb += sizeof(WORD);
|
|
}
|
|
else
|
|
// skip over one WORD, it's zero initialized already
|
|
pb += sizeof(WORD);
|
|
|
|
// empty create parameters
|
|
pb += sizeof(WORD);
|
|
pb = alignDWORD(pb);
|
|
|
|
*pcbDIT = (UINT)(pb - (PBYTE)*ppvDIT);
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT getDlgTemplateSize(LPCVOID pvDlg, LPDWORD pcbDlg)
|
|
{
|
|
PCDLGTEMPLATEEX pdt2;
|
|
LPCDLGTEMPLATE pdt; // for some weird reason there is no PCDLGTEMPLATE
|
|
PBYTE pb;
|
|
WORD cDlgItems,
|
|
cbCreateParams;
|
|
BOOL fEx;
|
|
|
|
//----- Initialization and parameter validation -----
|
|
if (pvDlg == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (pcbDlg == NULL)
|
|
return E_INVALIDARG;
|
|
*pcbDlg = 0;
|
|
|
|
//----- Parse through Dialog Template -----
|
|
UINT nStyleOffset, nDlgItemsOffset;
|
|
|
|
pdt = NULL;
|
|
pdt2 = (PCDLGTEMPLATEEX)pvDlg; // assume extended style
|
|
|
|
if (pdt2->signature == 0xFFFF) {
|
|
if (pdt2->dlgVer != 1)
|
|
return E_UNEXPECTED; // Chicago sanity check
|
|
|
|
nStyleOffset = (PBYTE)&pdt2->style - (PBYTE)pdt2;
|
|
nDlgItemsOffset = (PBYTE)&pdt2->cDlgItems - (PBYTE)pdt2;
|
|
|
|
pb = (PBYTE)(pdt2 + 1);
|
|
fEx = TRUE;
|
|
}
|
|
else {
|
|
pdt = (LPCDLGTEMPLATE)pvDlg;
|
|
pdt2 = NULL;
|
|
|
|
nStyleOffset = (PBYTE)&pdt->style - (PBYTE)pdt;
|
|
nDlgItemsOffset = (PBYTE)&pdt->cdit - (PBYTE)pdt;
|
|
|
|
pb = (PBYTE)(pdt + 1);
|
|
fEx = FALSE;
|
|
}
|
|
|
|
// skip over menu, window class and window text
|
|
pb = skipDlgString(pb);
|
|
pb = skipDlgString(pb);
|
|
pb = skipDlgString(pb);
|
|
|
|
// skip over font info: point size and typeface name
|
|
if (((*(PDWORD)((PBYTE)pvDlg + nStyleOffset)) & DS_SETFONT) != 0) {
|
|
pb += fEx ? sizeof(WORD) * 3 : sizeof(WORD);
|
|
pb = skipDlgString(pb);
|
|
}
|
|
|
|
// finally, adjust to DWORD boundary
|
|
pb = alignDWORD(pb);
|
|
|
|
//----- Parse through Dialog Item Templates -----
|
|
cDlgItems = *(PWORD)((PBYTE)pvDlg + nDlgItemsOffset);
|
|
if (cDlgItems > 0) {
|
|
while (cDlgItems-- > 0) {
|
|
pb += fEx ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE);
|
|
|
|
// skip over window class and window text
|
|
pb = skipDlgString(pb);
|
|
pb = skipDlgString(pb);
|
|
|
|
// skip create parameters
|
|
cbCreateParams = *((PWORD)pb);
|
|
if (fEx)
|
|
pb += sizeof(WORD) + cbCreateParams;
|
|
else
|
|
pb += cbCreateParams > 0 ? cbCreateParams : sizeof(WORD);
|
|
|
|
// point at the next dialog item
|
|
pb = alignDWORD(pb);
|
|
}
|
|
}
|
|
|
|
*pcbDlg = pb - (PBYTE)pvDlg;
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL loadDialogTemplate(HINSTANCE hinstDlg, UINT nID, PVOID *ppvDT, PDWORD pcbDT)
|
|
{
|
|
PVOID p;
|
|
HANDLE h;
|
|
|
|
if (hinstDlg == NULL)
|
|
return FALSE;
|
|
|
|
if (ppvDT == NULL)
|
|
return FALSE;
|
|
*ppvDT = NULL;
|
|
|
|
if (pcbDT == NULL)
|
|
return FALSE;
|
|
*pcbDT = 0;
|
|
|
|
h = FindResource(hinstDlg, MAKEINTRESOURCE(nID), RT_DIALOG);
|
|
if (h == NULL)
|
|
return FALSE;
|
|
|
|
*pcbDT = SizeofResource(hinstDlg, (HRSRC)h);
|
|
if (*pcbDT == 0)
|
|
return FALSE;
|
|
|
|
h = LoadResource(hinstDlg, (HRSRC)h);
|
|
if (h == NULL)
|
|
return FALSE;
|
|
|
|
p = LockResource(h);
|
|
if (p == NULL)
|
|
return FALSE;
|
|
|
|
*ppvDT = p;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
inline PBYTE skipDlgString(PBYTE pb)
|
|
{
|
|
PWCHAR pwch;
|
|
|
|
if (*((PWORD)pb) == 0xFFFF)
|
|
return (pb + sizeof(DWORD));
|
|
|
|
pwch = (PWCHAR)pb;
|
|
while (*pwch++ != L'\0')
|
|
;
|
|
|
|
return (PBYTE)pwch;
|
|
}
|
|
|
|
inline PBYTE alignDWORD(PBYTE pb)
|
|
{
|
|
return (PBYTE)(((UINT_PTR)pb + 3) & ~((UINT_PTR)3));
|
|
}
|
|
|
|
|
|
//----- IsTahomaFontExist helpers -----
|
|
|
|
int CALLBACK enumFontFamExProc(ENUMLOGFONTEX *, NEWTEXTMETRICEX *, int, LPARAM lParam)
|
|
{
|
|
(*(LPBOOL)lParam) = TRUE;
|
|
return 0;
|
|
}
|
|
|
|
|
|
//----- PropSheetProc helpers -----
|
|
|
|
void initializeBannerTextCtrlFont(HWND hWnd, INT nId)
|
|
{
|
|
NONCLIENTMETRICS ncm = {0};
|
|
TCHAR szFontSize[24];
|
|
INT nBigFontSize = 0;
|
|
LOGFONT BigBoldLogFont;
|
|
BOOL fUpdateFont = TRUE;
|
|
|
|
ZeroMemory(&BigBoldLogFont, sizeof(BigBoldLogFont));
|
|
|
|
ncm.cbSize = sizeof(ncm);
|
|
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0))
|
|
{
|
|
BigBoldLogFont = ncm.lfMessageFont;
|
|
fUpdateFont = FALSE;
|
|
}
|
|
|
|
BigBoldLogFont.lfWeight = FW_NORMAL;
|
|
if (!LoadString(g_rvInfo.hInst, IDS_BANNERFONT, BigBoldLogFont.lfFaceName, LF_FACESIZE))
|
|
StrCpy(BigBoldLogFont.lfFaceName, TEXT("Verdana"));
|
|
|
|
if (LoadString(g_rvInfo.hInst, IDS_BANNERFONTSIZE, szFontSize, countof(szFontSize)))
|
|
nBigFontSize = StrToInt(szFontSize);
|
|
if (nBigFontSize < 18)
|
|
nBigFontSize = 18;
|
|
|
|
HDC hdc = GetDC(hWnd);
|
|
if (hdc != NULL)
|
|
{
|
|
int dyLogPixPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
|
|
|
|
BigBoldLogFont.lfHeight = -MulDiv(dyLogPixPerInch, nBigFontSize, 72);
|
|
|
|
if (fUpdateFont)
|
|
{
|
|
TEXTMETRIC tm;
|
|
|
|
GetTextMetrics(hdc, &tm); // get the current textmetrics
|
|
BigBoldLogFont.lfCharSet = tm.tmCharSet;
|
|
}
|
|
|
|
g_hFont = CreateFontIndirect(&BigBoldLogFont);
|
|
ReleaseDC(hWnd, hdc);
|
|
|
|
if (g_hFont != NULL)
|
|
{
|
|
HWND hControl = GetDlgItem(hWnd, nId);
|
|
|
|
if (hControl)
|
|
SendMessage(hControl, WM_SETFONT, (WPARAM)g_hFont, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CALLBACK bannerTextCtrlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (uMsg == WM_PAINT)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc = BeginPaint(hWnd, &ps);
|
|
|
|
int iBkModeOld = SetBkMode(hdc, TRANSPARENT);
|
|
|
|
HFONT hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0);
|
|
HFONT hfontOld = (HFONT)SelectObject(hdc, hfont);
|
|
|
|
COLORREF rgbSav = SetTextColor(hdc, RGB(0xff, 0xff, 0xff));
|
|
RECT rect;
|
|
|
|
GetClientRect(hWnd, &rect);
|
|
DrawText(hdc, s_szBannerText, -1, &rect, DT_WORDBREAK | DT_LEFT);
|
|
|
|
SetTextColor(hdc, rgbSav);
|
|
SelectObject(hdc, hfontOld);
|
|
SetBkMode(hdc, iBkModeOld);
|
|
EndPaint(hWnd, &ps);
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
if (uMsg == WM_ERASEBKGND)
|
|
return (FALSE);
|
|
|
|
return (CallWindowProc(s_lpfnBannerTextCtrlProc, hWnd, uMsg, wParam, lParam));
|
|
}
|
|
|
|
void paintBmpInHdcRect(HBITMAP hBmp, HDC hDC, RECT rect)
|
|
{
|
|
BITMAP bm;
|
|
if(!GetObject(hBmp, sizeof(BITMAP), (LPVOID)(&bm)))
|
|
return;
|
|
|
|
HDC hdcMem = CreateCompatibleDC(hDC);
|
|
SelectObject(hdcMem, hBmp);
|
|
|
|
SetStretchBltMode(hDC, COLORONCOLOR);
|
|
StretchBlt(hDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
|
|
hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
|
|
|
|
DeleteDC(hdcMem);
|
|
}
|
|
|
|
void handleEraseBkgndMsg(HWND hDlg, HDC hDC)
|
|
{
|
|
RECT rectBmp;
|
|
|
|
GetClientRect(GetDlgItem(hDlg, IDC_BANNERBMPCTRL), &rectBmp);
|
|
|
|
RECT rect;
|
|
GetClientRect(hDlg, &rect);
|
|
rect.top = rectBmp.bottom;
|
|
|
|
HBRUSH hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
|
|
HBRUSH hbrSav = (HBRUSH)SelectObject(hDC, hbr);
|
|
Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);
|
|
|
|
paintBmpInHdcRect(g_hBannerBmp, hDC, rectBmp);
|
|
|
|
SelectObject(hDC, hbrSav);
|
|
DeleteObject((HGDIOBJ)hbr);
|
|
}
|
|
|
|
BOOL CALLBACK propertySheetWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (uMsg == WM_ERASEBKGND)
|
|
{
|
|
handleEraseBkgndMsg(hWnd, (HDC)wParam);
|
|
return TRUE;
|
|
}
|
|
else if (uMsg == WM_SIZE)
|
|
{
|
|
HWND hBannerWnd = GetDlgItem(hWnd, IDC_BANNERBMPCTRL);
|
|
|
|
// set the bitmap control width to the property sheet window width
|
|
if (hBannerWnd)
|
|
{
|
|
RECT rectBmp;
|
|
RECT rectText;
|
|
|
|
GetClientRect(s_hBannerWnd, &rectBmp);
|
|
SetWindowPos(s_hBannerWnd, HWND_TOP, 0, 0, LOWORD(lParam), rectBmp.bottom - rectBmp.top, SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
GetClientRect(s_hBannerText, &rectText);
|
|
SetWindowPos(s_hBannerText, HWND_TOP, 0, 0, LOWORD(lParam) - 14, rectText.bottom - rectText.top, SWP_NOMOVE | SWP_NOZORDER);
|
|
}
|
|
}
|
|
return (CallWindowProc(s_lpfnPSWndProc, hWnd, uMsg, wParam, lParam));
|
|
}
|