Paint issues
Hi,
I am using a control inheriting from CStatic(code provided at then end)
but I have one problem when I use it on pocket pc.
I use this CStatic as m_ctlText to display a text VERTICALLY CENTERED
and my CStatic is used in a CFormView called CMessageView.
void CMessageView::OnSize(UINT nType, int cx, int cy)
{
TRACE(_T("[0x%x]CMessageView::OnSize(%d, %d, %d)\n"), this, nType,
cx, cy);
// call ancestor
CBaseView::OnSize(nType, cx, cy);
//
if ( ::IsWindow(m_ctlText.GetSafeHwnd()) && ::IsWindow(m_hWnd) &&
(cx > 0) )
{
// Background Image
if (m_ePrevDisplayMode != DRA::GetDisplayMode())
{
// assign bitmap
HBITMAP hBmp = UIManager::GetInstance()->GetBitmap(
UIManager::BACKGROUND );
if ( hBmp != NULL ) {
m_ctlText.SetBitmap( hBmp, CxStatic::OriginalSize );
}
// remember now
m_ePrevDisplayMode = DRA::GetDisplayMode();
}
//
m_ctlText.MoveWindow( 0, 0 , cx, cy );
// Scroll bar info
SetScrollSizes( MM_TEXT, CSize(cx, cy) );
}
}
The problem is when I get the virtual keyboard(called SIP - see here
http://www.dotnetheaven.com/Uploadfile/jodonnell/SIPOnPocketPC01312006011457AM/Images/PocketPCSIPView1.jpg)
to be displayed, because my text is displayed two times one below the other.
One text is displayed centered just before to display the virtual
keyboard and the other is the message displayed centered when taking in
account the keyboard.
I don't understand why I have the two text displayed because when I look
at windows messages I get :
WM_WINDOPOSCHANGED
WM_WINDOPOSCHANGED
WM_WINDOPOSCHANGED
WM_WINDOPOSCHANGED
WM_WINDOPOSCHANGED
WM_WINDOPOSCHANGED
WM_WINDOPOSCHANGED
WM_WINDOPOSCHANGED
WM_PAINT
WM_ERASEBKGND
WM_GETTEXTLENGTH
WM_GETTEXT
WM_PAINT
WM_GETTEXTLENGTH
WM_GETTEXT
So when I am in the WM_PAINT I have the right rect values, here is what
I get when I my control is displayed for the first time
BEFORE DrawText : 0,0,268,240
BEFORE DrawText : 0,0,268,240
And then when I display the virtual keyboard:
BEFORE DrawText : 0,0,188,240
BEFORE DrawText : 0,0,188,240
So as you can see values seems OK.
I am a bit lost so If you have any suggestion ...
UPDATE : I have found that if if comment the following lines
if (m_ePrevDisplayMode != DRA::GetDisplayMode())
{} used to detect when passing from a landscape to portrait mode
it seems to fix my problem but in this case my image is reloaded several
times
********************************************
#include "stdafx.h"
#include "CxStatic.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifndef WM_MOUSELEAVE
#define WM_MOUSELEAVE 0x02A3
#endif
#ifndef DestroyCursor
#define DestroyCursor DestroyIcon
#endif
///////////////////////////////////////////////////////////////////////////////
// ctor
CxStatic::CxStatic()
{
hinst_msimg32 = NULL;
//m_strText = _T("");
m_bTransparentBk = FALSE;
m_bAutoWrapping = TRUE;
m_bAutoAdjustFont = FALSE;
m_bNotifyParent = FALSE;
m_bRounded = TRUE;
m_rgbText = ::GetSysColor(COLOR_WINDOWTEXT);
m_rgbBkgnd = ::GetSysColor(COLOR_CAPTIONTEXT);
m_cr3DHiliteColor = RGB(0,0,255);
m_rgbTransparent = 0xFF000000;
m_EDispMode = 0;
m_pBrush = new CBrush(m_rgbBkgnd);
m_fillmode = Normal;
m_crHiColor = m_rgbBkgnd;
m_crLoColor = m_rgbBkgnd;
m_nFontSize = m_nFontSizeVar = 8;
m_csFontFamilly = _T("");
m_bFont3d = FALSE;
m_hBitmap = NULL;
m_bBitmap = FALSE;
m_nResourceID = -1;
m_bHover = FALSE;
m_bTracking = FALSE;
m_bAllowMove = FALSE;
m_dwTxtFlags = 0;
m_blendfunc.BlendOp = AC_SRC_OVER;
m_blendfunc.BlendFlags = 0;
m_blendfunc.AlphaFormat = 0;
m_blendfunc.SourceConstantAlpha = 128;
m_bAutoSizing = FALSE;
m_strResourceName.Empty();
}
CxStatic::~CxStatic()
{
//TRACE(_T("in CxStatic::~CxStatic\n"));
// Clean up
if (m_pBrush){
delete m_pBrush;
m_pBrush = NULL;
}
if ( m_hBitmap )
::DeleteObject(m_hBitmap);
if ( hinst_msimg32 )
::FreeLibrary( hinst_msimg32 );
}
// CxStatic
BEGIN_MESSAGE_MAP(CxStatic, CStatic)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_MESSAGE(WM_SETTEXT, OnSetText)
ON_MESSAGE(WM_SETFONT, OnSetFont)
ON_WM_SIZE()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////////
//// PreSubclassWindow
void CxStatic::PreSubclassWindow()
{
//TRACE(_T("in CxStatic::PreSubclassWindow\n"));
m_dwTxtFlags = GetStyle();
// get current font
CFont* pFont = GetFont();
if (pFont == NULL){
pFont = CFont::FromHandle( (HFONT) ::GetStockObject(SYSTEM_FONT) );
}
// create the font for this control
LOGFONT lf;
pFont->GetLogFont(&lf);
m_font.CreateFontIndirect(&lf);
//this->GetWindowText(m_strText);
Invalidate();
//ReconstructFont();
}
void CxStatic::SetMoveable(BOOL moveAble)
{
ModifyStyle(0, SS_NOTIFY);
m_bAllowMove = moveAble;
}
///////////////////////////////////////////////////////////////////////////////
// SetBackgroundColor
void CxStatic::SetBkColor(COLORREF rgbBkgnd, COLORREF rgbBkgndHigh,
BackFillMode mode)
{
m_crLoColor = rgbBkgnd;
m_crHiColor = rgbBkgndHigh;
m_fillmode = mode;
m_rgbBkgnd = rgbBkgnd;
if (m_pBrush){
delete m_pBrush;
m_pBrush = new CBrush(m_rgbBkgnd);
}
else
m_pBrush = new CBrush(m_rgbBkgnd);
RedrawWindow();
}
/////////////////////////////////////////////////////////////////////////////////
//// SetTransparent
void CxStatic::SetTransparent(BOOL bTranspMode)
{
m_bTransparentBk = bTranspMode;
RedrawWindow();
}
void CxStatic::SetTextColor(COLORREF col)
{
m_rgbText = col;
RedrawWindow();
}
void CxStatic::SetAutoSizing(BOOL bAutoSizing)
{
m_bAutoSizing = bAutoSizing;
}
void CxStatic::SetAutoAdjustFont(BOOL bAutoAdjustFont)
{
m_bAutoAdjustFont = bAutoAdjustFont;
}
void CxStatic::SetRounded(BOOL bRounded){
m_bRounded = bRounded;
}
/////////////////////////////////////////////////////////////////////////////////
//// FONT
void CxStatic::SetFont(const CString& strFont,int nPointSize, int nWeight,
BOOL bRedraw /*= TRUE*/)
{
LOGFONT lf;
CFont* pFont = NULL;
memset(&lf, 0, sizeof(LOGFONT)); // Zero out the structure.
pFont = GetFont();
if (pFont == NULL){
pFont = CFont::FromHandle( (HFONT) ::GetStockObject(SYSTEM_FONT) );
}
pFont->GetLogFont( &lf );
if (strFont.IsEmpty() == FALSE)
_tcscpy(lf.lfFaceName,strFont); // Set Font Familly
if (nPointSize > 0)
lf.lfHeight = nPointSize; // Set Height
lf.lfWeight = nWeight; // Set Weight
SetFont(&lf, bRedraw);
}
void CxStatic::SetFont(LOGFONT *pLogFont, BOOL bRedraw /*= TRUE*/)
{
ASSERT(pLogFont);
if (!pLogFont)
return;
if (m_font.GetSafeHandle())
m_font.DeleteObject();
LOGFONT lf = *pLogFont;
m_font.CreateFontIndirect(&lf);
if (bRedraw)
RedrawWindow();
}
void CxStatic::SetFont(CFont *pFont, BOOL bRedraw /*= TRUE*/)
{
ASSERT(pFont);
if (!pFont)
return;
LOGFONT lf;
memset(&lf, 0, sizeof(lf));
pFont->GetLogFont(&lf);
SetFont(&lf, bRedraw);
}
LRESULT CxStatic::OnSetFont(WPARAM wParam, LPARAM lParam)
{
LRESULT lrReturn(Default());
SetFont(CFont::FromHandle((HFONT)wParam) );
RedrawWindow();
return lrReturn;
}
void CxStatic::SetFont3D(BOOL bFont3D, Type3D type)
{
m_bFont3d = bFont3D;
m_3dType = type;
RedrawWindow();
}
LRESULT CxStatic::OnSetText(WPARAM wParam, LPARAM lParam)
{
LRESULT lRet = Default();
Invalidate();
return lRet;
}
BOOL CxStatic::SetBitmap(HBITMAP hBitmap, ImageSize Emode, COLORREF
rgbTransparent)
{
m_bBitmap = TRUE;
if ( m_hBitmap ) {
::DeleteObject(m_hBitmap);
}
m_hBitmap = hBitmap;
//if (Emode == OriginalSize){
// CRect Rect;
// GetWindowRect(&Rect); // x,y -> screen
// ScreenToClient(&Rect); // screen -> to client ( view ou dialog)
// Rect.InflateRect(Rect.Width(),Rect.Height());
// SetWindowPos( NULL,0,0,Rect.Width(),Rect.Height(),SWP_NOMOVE
| SWP_NOZORDER); //
//}
Invalidate();
return ::GetObject(m_hBitmap, sizeof(BITMAP), &m_bmInfo);
}
BOOL CxStatic::SetBitmap(UINT nIDResource, ImageSize Emode, COLORREF
rgbTransparent)
{
m_nResourceID = nIDResource;
m_strResourceName.Empty();
m_bTransparentBk = FALSE;
HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(nIDResource),
IMAGE_BITMAP,
0,0,
LR_DEFAULTCOLOR);
if (!hBmp) return FALSE;
return CxStatic::SetBitmap(hBmp, Emode, rgbTransparent);
}
BOOL CxStatic::SetBitmap(LPCTSTR lpszResourceName, ImageSize Emode,
COLORREF rgbTransparent)
{
m_nResourceID = -1;
m_strResourceName = lpszResourceName;
#ifndef UNDER_CE
HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
lpszResourceName,
IMAGE_BITMAP,
0,0,
LR_DEFAULTCOLOR);
#else
HBITMAP hBmp = ::SHLoadImageFile( lpszResourceName );
if (!hBmp) return FALSE;
#endif
return CxStatic::SetBitmap(hBmp, Emode, rgbTransparent);
}
void CxStatic::Format(LPCTSTR szFmt, ...)
{
ULONG bytesWriten;
TCHAR szBuffer[2048];
va_list args;
va_start(args, szFmt);
bytesWriten = _vstprintf(szBuffer, szFmt, args);
SetWindowText( szBuffer );
va_end(args);
RedrawWindow();
}
void CxStatic::AppendText(LPCTSTR szFmt, ...)
{
ULONG bytesWriten;
TCHAR szBuffer[2048];
va_list args;
CString strTmp;
GetWindowText(strTmp);
va_start(args, szFmt);
bytesWriten = _vstprintf(szBuffer, szFmt, args);
va_end(args);
strTmp += szBuffer;
SetWindowText( strTmp );
RedrawWindow();
}
BOOL CxStatic::RedrawWindow()
{
Invalidate();
return TRUE;
}
void CxStatic::OnPaint()
{
CPaintDC dc(this); // device context for painting
CBitmap bmp;
CBitmap* pOldBitmap = NULL;
CString strText;
// GET Client area
CRect rect;GetClientRect(rect);
m_rc = rect;
//Double Buffering - Modify MemDC for transparent background but
doesn't work
// because I have to invalidate parent when SetWindowText - Need to
find a fix!!!
//pDC->SetBkColor(m_rgbBkgnd);
CMemDC MemDC(&dc, &rect, m_bTransparentBk);
// PAINT SOLID BACKGROUND IF NO BITMAP
if ( !m_bBitmap){
if ( !m_bTransparentBk ){
if (m_fillmode == Normal)
MemDC.FillRect(&rect, m_pBrush);
else
DrawGradientFill(&MemDC, &rect, m_fillmode);
}
}
else{// DISPLAY BACKGROUND BITMAP
//GetWindowText( strText);
DrawBitmap(&MemDC, &rect);
}
// TEXT RENDERING
GetWindowText( strText);
CFont* pOldFont = MemDC.SelectObject( &m_font );
COLORREF rgbText = MemDC.SetTextColor(m_rgbText);
TRACE(_T("BEFORE DrawText : %d,%d,%d,%d\n"),rect.top, rect.left,
rect.bottom, rect.right );
MemDC.DrawText( strText, &rect, DT_LEFT|DT_VCENTER|DT_CENTER);
//CxStatic::DrawText( &MemDC, &rect, strText );
// Restore DC's State
MemDC.SelectObject(pOldFont);
MemDC.SetTextColor(rgbText);
}
void CxStatic::DrawBitmap(CDC* pDCMem, CRect* pRect)
{
CRect rect;
GetClientRect( rect );
BOOL bRet = FALSE;
if (!m_hBitmap)
return;
CDC dcMem;
VERIFY( dcMem.CreateCompatibleDC(pDCMem) );
m_bTransparentBk = FALSE;
// Select bitmap
HBITMAP* pBmpOld = (HBITMAP*) ::SelectObject(pDCMem->m_hDC, m_hBitmap);
pDCMem->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(),
&dcMem, 0, 0, m_bmInfo.bmWidth, m_bmInfo.bmHeight,
SRCCOPY);
}
///////////////////////////////////////////////////////////////////////////////
// OnEraseBkgnd
BOOL CxStatic::OnEraseBkgnd(CDC* pDC)
{
Invalidate(FALSE);
return FALSE;
}
void CxStatic::OnSize(UINT nType, int cx, int cy)
{
TRACE( _T("CxStatic::OnSize(%d,%d,%d)\n"), nType, cx,cy );
CStatic::OnSize(nType, cx, cy);
Invalidate();
}