www.pudn.com > RGNCdraw.zip > RGNDLG.CPP


// 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 
}