// DlgEx.cpp : implementation file
//
#include "stdafx.h"
#include "rgndemo.h"
#include "RGNDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CRGNDlg dialog
CRGNDlg::CRGNDlg(UINT nIDTemplate,CWnd* pParent,CString rgnfile)
: CDialog(nIDTemplate, pParent)
{
//{{AFX_DATA_INIT(CRGNDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_bTrackMove = FALSE;
m_rgnfile = rgnfile;
m_xScale = 1;
m_yScale = 1;
}
CRGNDlg::~CRGNDlg()
{
}
void CRGNDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CRGNDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CRGNDlg, CDialog)
//{{AFX_MSG_MAP(CRGNDlg)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRGNDlg message handlers
BOOL CRGNDlg::OnInitDialog()
{
/*scaling for the 'small fonts' / 'large fonts' problem
The problem:
------------
For example you have "small fonts" selected in your desktop display config.
You happily create your dialog box , put in your bmp and insert
all the required controls aligning them carefully to the background bmp.
You then triumphantly send out your app and then get people complaining
that things don't line up.
The cause:
----------
These people have 'large fonts' selected. Windows scales the dialog box and
its controls according to the font. The font in turn is dependent on the
'small/large' font setting - so Ms Sans Serif 8 is not the same 'size'.
Since the image and the rgn are pixel based there is a problem.
The solution:
-------------
There are two possible solutions -
1. Scaling
This is what I have implemented here.
What you do is design your dialog and image using the
mode (small fonts or large fonts) that the app is going to
be used in.
This is a bit crude I know but the first time your create your
dialog put a break on
MapDialogRect(rect);
execute to it and see what it converts the rect.right and rect.bottom
to. DESIGNX is then set to rect.right and DESIGNY to rect.bottom.
So when I designed this they were 150 and 163.
The drawback of scaling is that it is not exact.
E.g. Scaling from an app designed in "small fonts" is a bit blocky
if scaled up for "large fonts".
2. Have two separate images and two RGN files.
I suggest that you design your dialog and then base two dialogs
on the original one and setup one to use large image and one to use
the smaller image.
A "reliable" way of determing the font mode is
if (dc.GetDeviceCaps(LOGPIXELSX) == 120) then its large
else its small //dc.GetDeviceCaps(LOGPIXELSX)==96
Tis not my fault.
*/
int DESIGNX = 150;
int DESIGNY = 163;
CRect rect;
rect.SetRect(0,0,100,100);
MapDialogRect(rect);
m_xScale = (float)((float)rect.right / (float) DESIGNX);
m_yScale = (float)((float)rect.bottom / (float) DESIGNY);
GetClientRect(rect);
GetDlgItem(IDC_BKIMAGE)->MoveWindow(rect);
HRSRC hResInfo;
HGLOBAL hGlobal;
hResInfo = FindResource(AfxGetInstanceHandle(), m_rgnfile,"RGN");
hGlobal = LoadResource(NULL,hResInfo);
if (hGlobal) {
BYTE *rgndata = (BYTE FAR*)LockResource(hGlobal);
if (rgndata) {
HRGN rgn;
XFORM xform;
xform.eM11 = (FLOAT) m_xScale;
xform.eM22 = (FLOAT) m_yScale;
xform.eM12 = (FLOAT) 0.0;
xform.eM21 = (FLOAT) 0.0;
xform.eDx = (FLOAT) 0.0;
xform.eDy = (FLOAT) 0.0;
m_dialogrgn = ExtCreateRegion(&xform,sizeof(RGNDATAHEADER) + (sizeof(RECT) * ((RGNDATA*)rgndata)->rdh.nCount),(RGNDATA*)rgndata);
VERIFY(m_dialogrgn!=NULL); // if you want more comprehensive checking - feel free!
rgn = ExtCreateRegion(&xform, sizeof(RGNDATAHEADER) + (sizeof(RECT) * ((RGNDATA*)rgndata)->rdh.nCount),(RGNDATA*)rgndata);
VERIFY(rgn!=NULL); // if you want more comprehensive checking - feel free!
::SetWindowRgn(m_hWnd, rgn, TRUE);
::UnlockResource(hGlobal);
}
}
if(hGlobal) ::FreeResource(hGlobal);
CDialog::OnInitDialog();
return TRUE;
}
BOOL CRGNDlg::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CRGNDlg::InvertTracker(CPoint point)
{
//just invert outline - slow for complex regions
HRGN rgn1;
rgn1 = CreateRectRgn(0, 0,1,1);
CBrush b;
b.CreateSolidBrush(RGB(0,0,255));
CombineRgn(rgn1,m_dialogrgn,NULL,RGN_COPY);
OffsetRgn(rgn1,point.x-m_ptMouse.x,point.y-m_ptMouse.y);
SetROP2(m_dc.m_hDC,R2_NOT);
FrameRgn(m_dc.m_hDC,rgn1,(HBRUSH)b.m_hObject,2,2);
b.DeleteObject();
DeleteObject(rgn1);
//otherwise invert entire region - fast
/*HRGN rgn1;
rgn1 = CreateRectRgn(0, 0,1,1);
CBrush b;
b.CreateSolidBrush(RGB(0,0,255));
CombineRgn(rgn1,m_dialogrgn,NULL,RGN_COPY);
OffsetRgn(rgn1,point.x-m_ptMouse.x,point.y-m_ptMouse.y);
SetROP2(m_dc.m_hDC,R2_NOT);
FrameRgn(m_dc.m_hDC,rgn1,(HBRUSH)b.m_hObject,2,2);
b.DeleteObject();
DeleteObject(rgn1);
*/
}
void CRGNDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
m_dc.Attach(::GetDC(NULL));
m_bTrackMove = TRUE;
m_ptMouse = point;
SetCapture();
ClientToScreen(&point);
InvertTracker(point);
m_ptLast = point;
}
void CRGNDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bTrackMove)
{
m_bTrackMove=FALSE;
ReleaseCapture();
InvertTracker(m_ptLast);
::ReleaseDC(NULL,m_dc.Detach());
ClientToScreen(&point);
SetWindowPos(NULL, point.x-m_ptMouse.x, point.y-m_ptMouse.y,0,0,
SWP_NOZORDER|SWP_NOSIZE);
ShowWindow(SW_SHOW);
}
else CDialog::OnLButtonUp(nFlags, point);
}
void CRGNDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if (m_bTrackMove)
{
ClientToScreen(&point);
InvertTracker(m_ptLast);
m_ptLast = point;
InvertTracker(m_ptLast);
}
else CDialog::OnMouseMove(nFlags, point);
}
void CRGNDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
}