/****************************************************
Set dialog DPI helper class
Copyright (C)2003 by George Yohng
http://www.yohng.com
LICENSE AGREEMENT:
You agree to go to http://www.yohng.com/music.html
and listen completely (without skips) to the very
first track on the list.
****************************************************/
#include <stdafx.h>
#include <windows.h>
#include "setdpi.h"
class helper
{
public:
// Constants used in DLGINIT resources for OLE control containers
// NOTE: These are NOT real Windows messages they are simply tags
// used in the control resource and are never used as 'messages'
enum
{
ATL_WM_OCC_LOADFROMSTREAM = 0x0376,
ATL_WM_OCC_LOADFROMSTORAGE = 0x0377,
ATL_WM_OCC_INITNEW = 0x0378,
ATL_WM_OCC_LOADFROMSTREAM_EX = 0x037A,
ATL_WM_OCC_LOADFROMSTORAGE_EX = 0x037B,
ATL_DISPID_DATASOURCE = 0x80010001,
ATL_DISPID_DATAFIELD = 0x80010002,
};
//local struct used for implementation
#pragma pack(push, 1)
struct DLGINITSTRUCT
{
WORD nIDC;
WORD message;
DWORD dwSize;
};
struct DLGTEMPLATEEX
{
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
// Everything else in this structure is variable length,
// and therefore must be determined dynamically
// sz_Or_Ord menu; // name or ordinal of a menu resource
// sz_Or_Ord windowClass; // name or ordinal of a window class
// WCHAR title[titleLen]; // title string of the dialog box
// short pointsize; // only if DS_SETFONT is set
// short weight; // only if DS_SETFONT is set
// short bItalic; // only if DS_SETFONT is set
// WCHAR font[fontLen]; // typeface name, if DS_SETFONT is set
};
struct DLGITEMTEMPLATEEX
{
DWORD helpID;
DWORD exStyle;
DWORD style;
short x;
short y;
short cx;
short cy;
DWORD id;
// Everything else in this structure is variable length,
// and therefore must be determined dynamically
// sz_Or_Ord windowClass; // name or ordinal of a window class
// sz_Or_Ord title; // title string or ordinal of a resource
// WORD extraCount; // bytes following creation data
};
#pragma pack(pop)
static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
{
return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
}
inline static WORD& DlgTemplateItemCount(DLGTEMPLATE* pTemplate)
{
if (IsDialogEx(pTemplate))
return reinterpret_cast<DLGTEMPLATEEX*>(pTemplate)->cDlgItems;
else
return pTemplate->cdit;
}
inline static const WORD& DlgTemplateItemCount(const DLGTEMPLATE* pTemplate)
{
if (IsDialogEx(pTemplate))
return reinterpret_cast<const DLGTEMPLATEEX*>(pTemplate)->cDlgItems;
else
return pTemplate->cdit;
}
static DLGITEMTEMPLATE* FindFirstDlgItem(const DLGTEMPLATE* pTemplate)
{
BOOL bDialogEx = IsDialogEx(pTemplate);
WORD* pw;
DWORD dwStyle;
if (bDialogEx)
{
pw = (WORD*)((DLGTEMPLATEEX*)pTemplate + 1);
dwStyle = ((DLGTEMPLATEEX*)pTemplate)->style;
}
else
{
pw = (WORD*)(pTemplate + 1);
dwStyle = pTemplate->style;
}
// Check for presence of menu and skip it if there is one
// 0x0000 means there is no menu
// 0xFFFF means there is a menu ID following
// Everything else means that this is a NULL terminated Unicode string
// which identifies the menu resource
if (*pw == 0xFFFF)
pw += 2; // Has menu ID, so skip 2 words
else
while (*pw++); // Either No menu, or string, skip past terminating NULL
// Check for presence of class name string
// 0x0000 means "Use system dialog class name"
// 0xFFFF means there is a window class (atom) specified
// Everything else means that this is a NULL terminated Unicode string
// which identifies the menu resource
if (*pw == 0xFFFF)
pw += 2; // Has class atom, so skip 2 words
else
while (*pw++); // Either No class, or string, skip past terminating NULL
// Skip caption string
while (*pw++);
// If we have DS_SETFONT, there is extra font information which we must now skip
if (dwStyle & DS_SETFONT)
{
// If it is a regular DLGTEMPLATE there is only a short for the point size
// and a string specifying the font (typefacename). If this is a DLGTEMPLATEEX
// then there is also the font weight, and bItalic which must be skipped
if (bDialogEx)
pw += 3; // Skip font size, weight, (italic, charset)
else
pw += 1; // Skip font size
while (*pw++); // Skip typeface name
}
// Dword-align and return
return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + 3) & ~3);
}
// Given the current dialog item and whether this is an extended dialog
// return a pointer to the next DLGITEMTEMPLATE*
static DLGITEMTEMPLATE* FindNextDlgItem(DLGITEMTEMPLATE* pItem, BOOL bDialogEx)
{
WORD* pw;
// First skip fixed size header information, size of which depends
// if this is a DLGITEMTEMPLATE or DLGITEMTEMPLATEEX
if (bDialogEx)
pw = (WORD*)((DLGITEMTEMPLATEEX*)pItem + 1);
else
pw = (WORD*)(pItem + 1);
if (*pw == 0xFFFF) // Skip class name ordinal or string
pw += 2; // (WORDs)
else
while (*pw++);
if (*pw == 0xFFFF) // Skip title ordinal or string
pw += 2; // (WORDs)
else
while (*pw++);
WORD cbExtra = *pw++; // Skip extra data
// cbExtra includes the size WORD in DIALOG resource.
if (cbExtra != 0 && !bDialogEx)
cbExtra -= 2;
// Dword-align and return
return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + cbExtra + 3) & ~3);
}
};
struct dialogdata_t
{
int pt,has_menu;
unsigned weight;
BOOL italic;
LPCWSTR faceName;
};
static void getptsize( HDC &dc, HFONT &font, SIZE *pSize )
{
HFONT oldfont = 0;
static char *sym = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
SIZE sz;
TEXTMETRICA t;
oldfont = (HFONT)SelectObject(dc,font);
GetTextMetricsA(dc,&t);
GetTextExtentPointA(dc,sym, 52, &sz);
pSize->cy = t.tmHeight;
pSize->cx = (sz.cx / 26 + 1) / 2;
SelectObject(dc,oldfont);
}
#define word_at(ptr) (*(WORD *)(ptr))
#define dword_at(ptr) (*(DWORD *)(ptr))
static void querydialogdata( LPCSTR data, dialogdata_t * result )
{
WORD *p = (WORD *)data;
unsigned long rstyle = dword_at(p);
int dialogex=0;
p += 2;
if (rstyle == 0xffff0001)
{
p+=4;
rstyle=dword_at(p);
p+=2;
dialogex=1;
}else
p+=2;
p+=5;
// Skip menu
switch(word_at(p))
{
case 0x0000: // no menu name
result->has_menu=0;
p++;
break;
case 0xffff: // has menu
result->has_menu=1;
p += 2;
break;
default: // has menu
result->has_menu=1;
p+=wcslen((LPCWSTR)p)+1;
break;
}
// skip class name
switch(word_at(p))
{
case 0x0000:
p++;
break;
case 0xffff:
p += 2;
break;
default:
p+=wcslen((LPCWSTR)p)+1;
break;
}
// skip the caption
p+=wcslen((LPCWSTR)p)+1;
// get the font name
if (rstyle & DS_SETFONT)
{
result->pt = word_at(p); p++;
if (dialogex)
{
result->weight = word_at(p); p++;
result->italic = LOBYTE(word_at(p)); p++;
}else
{
result->weight = FW_DONTCARE;
result->italic = FALSE;
}
result->faceName = (LPCWSTR)p;
p += wcslen( result->faceName ) + 1;
}else
{
result->faceName=L"Tahoma"; // TODO: put system font name here
result->pt=8; // TODO
result->weight=FW_NORMA