Thomas Stockbruegger
asked on
Need some help with SetBkMode(TRANSPARENT) and OnTimer
In OnCreate(LPCREATESTRUCT lpCreateStruct) of my View Class I put the timer and create the Static Text
CStatic *pStatic=new CStatic;
pStatic->Create(_T(""),WS_ CHILD|WS_V ISIBLE|SS_ CENTER,CRe ct(10,1,15 0,50),this ,IDC_STATI C_TEXT);
//---------------- für Datum / KW / Zeit ---------------
SetTimer(1,1000,NULL); // siehe OnTimer
//------------------------ ---------- ---------- ----------
In OnTimer(UINT nIDEvent) I wrote the following :
CTime time=CTime::GetCurrentTime ();
m_str_Zeit = time.Format("%H:%M:%S ");
m_str_Datum = time.Format("%d.%m.%Y KW:");
m_str_KW = time.Format("%U");
GetDlgItem(IDC_STATIC_TEXT )->SetWind owText(m_s tr_Zeit+m_ str_Datum+ m_str_KW);
CRect rect;
GetDlgItem(IDC_STATIC_TEXT )->GetWind owRect(&re ct);
ScreenToClient(&rect);
InvalidateRect(&rect);
UpdateWindow();
In OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) I did the following:
{
HBRUSH hbr = CView::OnCtlColor(pDC, pWnd, nCtlColor);
if(pWnd->GetDlgCtrlID()==I DC_STATIC_ TEXT)
{
pDC->SetBkMode(TRANSPARENT );
return reinterpret_cast<HBRUSH>(: :GetStockO bject(NULL _PEN));
}
else
{
return hbr;
}
}
The problem: I would like to show the user the date and time (time running) . I have the transparent text but you see a rectangle in white blinking. How can I fix this?
CStatic *pStatic=new CStatic;
pStatic->Create(_T(""),WS_
//---------------- für Datum / KW / Zeit ---------------
SetTimer(1,1000,NULL); // siehe OnTimer
//------------------------
In OnTimer(UINT nIDEvent) I wrote the following :
CTime time=CTime::GetCurrentTime
m_str_Zeit = time.Format("%H:%M:%S ");
m_str_Datum = time.Format("%d.%m.%Y KW:");
m_str_KW = time.Format("%U");
GetDlgItem(IDC_STATIC_TEXT
CRect rect;
GetDlgItem(IDC_STATIC_TEXT
ScreenToClient(&rect);
InvalidateRect(&rect);
UpdateWindow();
In OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) I did the following:
{
HBRUSH hbr = CView::OnCtlColor(pDC, pWnd, nCtlColor);
if(pWnd->GetDlgCtrlID()==I
{
pDC->SetBkMode(TRANSPARENT
return reinterpret_cast<HBRUSH>(:
}
else
{
return hbr;
}
}
The problem: I would like to show the user the date and time (time running) . I have the transparent text but you see a rectangle in white blinking. How can I fix this?
ASKER
Hello Sara,
thank you for your answer.
This looks better.... no blinking rectangle but the same problem that I had before with dc.textout:
take a look at my bitmap. The time is writing all over .
CWnd * pStatic = GetDlgItem(IDC_STATIC_TEXT );
pStatic->SetWindowText(str CurrentTim e);
pStatic->UpdateWindow();
Also I do not know why I don´t even stop at OnDraw with a breakpoint. So I can not draw anything there.
void CStockbrueggerView::OnDraw (CDC* pDC)
{
CStockbrueggerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
Int x=0; //try to stop here with breakpoint
thank you for your answer.
This looks better.... no blinking rectangle but the same problem that I had before with dc.textout:
take a look at my bitmap. The time is writing all over .
CWnd * pStatic = GetDlgItem(IDC_STATIC_TEXT
pStatic->SetWindowText(str
pStatic->UpdateWindow();
if that doesn't work either, you might try to not using a CStatic but use the OnDraw function of your view to write the new time with DrawText directly to the view's surface. use a member of your view class to decide whether you should draw the whole view or only update the timer.
Also I do not know why I don´t even stop at OnDraw with a breakpoint. So I can not draw anything there.
use a member of your view class to decide whether you should draw the whole view or only update the timer.I do not know how to do this.
void CStockbrueggerView::OnDraw
{
CStockbrueggerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
Int x=0; //try to stop here with breakpoint
ASKER
I only can draw something in OnPaint to the viewscreen
ASKER
I only can draw something in OnPaint to the viewscreenbut in your picture you are drawing the date/time to the view screen. an mfc view has a virtual OnDraw function which was called as a handler to the WM_PAINT message.
if you first draw the picture and second draw the text of the time info, you should have no issues with the transparent background.
to get only the time info updated (to not get flicker issues) you could evaluate the invalid rectangle in the OnDraw. that way you only would draw the part of the picture which is covered by the time info text (in order to clear the old time info) and then draw the text of the new info.
i think, the OnCtlColor didn't work correctly because the picture and the static control were not drawn in the correct order. is the picture also a control? if so, you might have better luck as two child controls of a view would be drawn in tab order what simply is the order the controls were subclassed. subclassing of controls was done in a dialog or formview in the OnInitDialog respectively the OnInitialUpdate function. if you create controls on the fly you would need to assign the controls yourself and/or add an own WindowsProc function that evaluates the windows messages. that is why you should consider to using a CFormView as a base even if you were drawing only pictures. if the picture was drawn to a (huge) owner-draw button or to a frame control instead of painting it directly to the client area of the view, the clock control could be placed directly above the picture control and and subclassing + drawing should work as expected as the OnCtlColor would be called for the static control.
Sara
ASKER
but in your picture you are drawing the date/time to the view screen. an mfc view has a virtual OnDraw function which was called as a handler to the WM_PAINT message.
I draw the background and text only in OnPaint. Any code in OnDraw will not execude, if I put there a breakpoint I got not stop!
So I do not know how to change that.
Any code in OnDraw will not executeif you were overwriting the OnPaint the default view handling was not executed since the OnDraw function would be called from the CView::OnPaint (or CScrollView::OnPaint or CFormView::OnPaint).
so, you should comment your own implementation of OnPaint (and comment the entry in the MESSAGE_MAP if any) and if OnDraw was called then, move the drawing code from OnPaint to OnDraw.
is the view part of an SDI or MDI solution? such that you were using a doctemplate to creating a triple of document, frame and view?
did you derive an own view class from CView and are you using CMainFrame and or a CMDIChildWnd derived frame class which is parent of your view?
generally, also the YourView::OnPaint should be able to draw a time info text above a picture. the difficulty is to save the picture in the rectangle where the time info would be drawn and restore only this part if the time was updated. MFC can't help you with this if picture and time info is not in child controls.
Sara
ASKER
I think I have a SDI, with CMainFrame, CDocument, and CView.
This is a short version of my OnPaint()
did you derive an own view class from CViewNO
This is a short version of my OnPaint()
void CStockbrueggerView::OnPaint()
{
CPaintDC dc(this); // device context for painting
CBitmap x_bitmap;
CDC MemDCBild;
if(m_Hintergrundbild==0) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_FIRMA_CLASSIC);
if(m_Hintergrundbild==1) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_FIRMA_CLASSIC);
if(m_Hintergrundbild==2) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_BOAT);
if(m_Hintergrundbild==3) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_MONUMENT_VALLEY);
if(m_Hintergrundbild==4) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_MALEDIVEN);
if(m_Hintergrundbild==5) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_NEUSCHWANSTEIN);
if(m_Hintergrundbild==6) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_NEW_YORK);
if(m_Hintergrundbild==7) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_VOGEL);
if(m_Hintergrundbild==8) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_WING);
if(m_Hintergrundbild==9) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_WEIHNACHTEN1);
if(m_Hintergrundbild==10) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_WINTER_BARN);
if(m_Hintergrundbild==11) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_KERMIT);
if(m_Hintergrundbild==12) x_bitmap.LoadBitmap(IDB_BITMAP_HINTERGRUNDBILD_PYRENEES);
MemDCBild.CreateCompatibleDC(&dc);
CBitmap *BmpPrevious = MemDCBild.SelectObject(&x_bitmap);
dc.BitBlt(0,0,2500,1000,&MemDCBild,0,0,SRCCOPY);
MemDCBild.SelectObject( BmpPrevious );
x_bitmap.DeleteObject();
.
.
.
.
.
}
ASKER
int CMainFrame::OnCreate(LPCRE ATESTRUCT lpCreateStruct)
{
.
.
.
if (!m_wndDlgBar.Create(this, IDR_MAINFRAME,
CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR))
{
TRACE0("Dialogfeldleiste konnte nicht erstellt werden\n");
return -1; // Fehler bei Erstellung
}
If the time will not work with the Cview Class, is it possible to set the time to IDR_MAINFRAME, because of the background there is no problem with the transparent mode. But how can I draw or textout the time there ?
{
.
.
.
if (!m_wndDlgBar.Create(this,
CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR))
{
TRACE0("Dialogfeldleiste konnte nicht erstellt werden\n");
return -1; // Fehler bei Erstellung
}
If the time will not work with the Cview Class, is it possible to set the time to IDR_MAINFRAME, because of the background there is no problem with the transparent mode. But how can I draw or textout the time there ?
ASKER
sara,
I found a way, that was easy.
I have enclosed OnPaint() at my CMainFrame and also the timer.
I have used the m_wndDlgBar for that.
//######################## ########## ########## ########## #####
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
m_wndDlgBar.GetDlgItem(IDC _STATIC_TE XT)->SetWi ndowText(m _str_Zeit+ m_str_Datu m+m_str_KW );
}
//######################## ########## ########## ########## #####
void CMainFrame::OnTimer(UINT nIDEvent)
{
CTime time=CTime::GetCurrentTime ();
m_str_Zeit = time.Format("%H:%M:%S ");
m_str_Datum = time.Format("%d.%m.%Y KW:");
m_str_KW = time.Format("%U");
m_wndDlgBar.GetDlgItem(IDC _STATIC_TE XT)->SetWi ndowText(m _str_Zeit+ m_str_Datu m+m_str_KW );
CFrameWnd::OnTimer(nIDEven t);
}
//######################## ########## ########## ########## #####
I found a way, that was easy.
I have enclosed OnPaint() at my CMainFrame and also the timer.
I have used the m_wndDlgBar for that.
//########################
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
m_wndDlgBar.GetDlgItem(IDC
}
//########################
void CMainFrame::OnTimer(UINT nIDEvent)
{
CTime time=CTime::GetCurrentTime
m_str_Zeit = time.Format("%H:%M:%S ");
m_str_Datum = time.Format("%d.%m.%Y KW:");
m_str_KW = time.Format("%U");
m_wndDlgBar.GetDlgItem(IDC
CFrameWnd::OnTimer(nIDEven
}
//########################
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you for your help.
Best regards.
Thomas
Best regards.
Thomas
if it is not a formview you may move the creation of the static control into the OnInitialUpdate function. you also should use a member (pointer or object) such that the control could be freed or deleted when you close the view.
the call of UpdateWindow would send a WM_PAINT message to the view window what probably is responsible for the wrong display. you may try instead:
Open in new window
if that doesn't work either, you might try to not using a CStatic but use the OnDraw function of your view to write the new time with DrawText directly to the view's surface. use a member of your view class to decide whether you should draw the whole view or only update the timer.
Sara