 |
|
 |
I really dig your simple and easy to use controls Chris - thanks a million in general!
I was having problems with setting CProgressCtrl in marquee mode with _WIN32_WINNT (running Windows 7) and tried using this control instead. Unfortunately I can't get it to compile for me. Similar problems: it reports needing _WIN32_WINNT to be at least 0x0403, but when you set this, it then needs it to be 0x0500 and then a whole can of worms spills onto the output screen
Anyway, maybe others are having this problem too, or I'm doing something silly. Anyone any advice?! Thanks
|
|
|
|
 |
|
 |
Great job! It helps me a lot.
|
|
|
|
 |
|
 |
i compiled the demo project, compiled and ran without any problem
then moved the source code for the progress control and added it to my project and it took less than 2 minutes to integrate it to my application.
really nice. thanks
|
|
|
|
 |
|
 |
I had a minor problem: When a I created a dialog that overlaps with the progress bar and the dialog was closed, the
control wasn't redraw correctly.
To fix this change the OnEraseBkgnd message handler
BOOL CTextProgressCtrl::OnEraseBkgnd(CDC* /*pDC*/)
{
Invalidate();
return TRUE;
}
|
|
|
|
 |
|
 |
This Modification can change the bouncing Progress-Bar into a scrolling Progress-Bar.
Add to .h :
Global:
#ifndef PBM_SETSCROLL
#define PBM_SETSCROLL (WM_USER+12)
#endif
Class:
inline BOOL SetScroll(BOOL bOn)
{ ASSERT(::IsWindow(m_hWnd)); return ((BOOL) ::SendMessage(m_hWnd, PBM_SETSCROLL, (WPARAM)bOn, 0)); }
...
afx_msg LRESULT OnSetScroll(WPARAM bShow, LPARAM);
...
BOOL m_bScroll;
Add to .cpp :
Constructor:
m_bScroll = False;
Message Map:
ON_MESSAGE(PBM_SETSCROLL, OnSetScroll)
New Function:
LRESULT CTextProgressCtrl::OnSetScroll(WPARAM bShow, LPARAM)
{
// call a common routine to redraw window
CommonPaint();
// set new percent completed display state, returning old one
BOOL bOldShow = m_bScroll;
m_bScroll = (BOOL)bShow;
return ((LRESULT)bOldShow);
}
In OnTimer change:
if ((nDirection == 1) && (nPosition >= nMax))
nDirection = -1;
else if ((nDirection == -1) && (nPosition <= m_nMin))
nDirection = +1;
to:
if(m_bScroll)
{
if(nPosition >= nMax) nPosition = m_nMin;
}
else
{
if ((nDirection == 1) && (nPosition >= nMax))
nDirection = -1;
else if ((nDirection == -1) && (nPosition <= m_nMin))
nDirection = +1;
}
That's it.
|
|
|
|
 |
|
 |
this code below add "Time Remaining" to TextProgressCtrl !!!
in .h you have to add :
inline BOOL SetShowTimeRemaining(BOOL bShow)
{ ASSERT(::IsWindow(m_hWnd)); m_dwTimer=GetTickCount(); return ((BOOL) ::SendMessage(m_hWnd, PBM_SETSHOWTIMEREMAINING, (WPARAM)bShow, 0)); }
...
afx_msg LRESULT OnSetShowTimeRemaining(WPARAM bShow, LPARAM);
...
DWORD m_dwTimer;
BOOL m_bShowTimeRemaining;
in .cpp you have to add :
m_dwTimer=GetTickCount();
m_bShowTimeRemaining = TRUE;
...
ON_MESSAGE(PBM_SETSHOWTIMEREMAINING, OnSetShowTimeRemaining)
inline CString ToHMS(DWORD dwTime)
{
CString str;
int iHours=dwTime/3600;
str.Format("%d:%02d:%02d",iHours,dwTime/60-iHours*60,dwTime%60);
return str;
}
LRESULT CTextProgressCtrl::OnSetShowTimeRemaining(WPARAM bShow, LPARAM)
{
// call a common routine to redraw window
CommonPaint();
// set new percent completed display state, returning old one
BOOL bOldShow = m_bShowTimeRemaining;
m_bShowTimeRemaining = (BOOL)bShow;
return ((LRESULT)bOldShow);
}
in OnPaint() method, below if(m_bshowPercent) str.AppendFormat(_T("%d%%"), (int)((dFraction * 100.0) + 0.5));
if (m_bShowTimeRemaining)
{
if(m_nPos>0)
{
DWORD dwElapsed = (GetTickCount()-m_dwTimer)/1000; // Time Elapsed
DWORD dwRemaining = (dwElapsed*m_nMax/m_nPos)-dwElapsed; // Time Remaining
str.AppendFormat(_T(" - EstimatedTimeRemaining: %s"),ToHMS(dwRemaining));
}
}
Regards, OCH
-- modified at 7:12 Wednesday 29th August, 2007
|
|
|
|
 |
|
 |
Hello Chris,
I have a out question out of scope of this article
I use C# so I was wondering if u know how to get the windows constants values
for these especially:
DT_BOTTOM
DT_CALCRECT
DT_CENTER
DT_END_ELLIPSIS
DT_MODIFYSTRING
DT_EXPANDTABS
DT_EXTERNALLEADING
DT_HIDEPREFIX
DT_INTERNAL
DT_LEFT
DT_MODIFYSTRING
DT_NOCLIP
DT_NOFULLWIDTHCHARBREAK
DT_NOPREFIX
DT_PATH_ELLIPSIS
DT_PREFIXONLY
DT_RIGHT
DT_RTLREADING
DT_SINGLELINE
DT_TABSTOP
DT_TOP
DT_VCENTER
DT_WORDBREAK
DT_WORD_ELLIPSIS
Thanks
|
|
|
|
 |
|
 |
Great class, thanks!
Question:
Class CMemDC differs from it's original version by Keith Rule. I've encountered some strange behavior with this version. Where did you get this version?
Live and let live!
|
|
|
|
 |
|
 |
The version in this class is oooold. I'd highly recommend using the latest version from Keith
cheers,
Chris Maunder
CodeProject.com : C++ MVP
|
|
|
|
 |
|
 |
Wonderful class - thanks guys. Only one little fault.
The SetMarquee function only works properly to turn marquee mode ON - doesn't turn if off completely.
I changed OnSetMarquee() to be as follows:
// set marquee style
if ((BOOL)bShow)
ModifyStyle(0, PBS_MARQUEE);
else
ModifyStyle(PBS_MARQUEE, 0);
// can't have percent complete for this style
m_bShowPercent = !(BOOL)bShow;
Change is not made without inconvenience, even from worse to better.
Samuel Johnson
|
|
|
|
 |
|
 |
Hi,
First let me tell you thanks - this is a really nice class. Very useful and easy to use. I just wanted to share a couple of comments that may help clarify what I found and also help anyone who may encounter the same.
I got this to work fine on VC++ 2005, after making a change in the TextProgressCtrl.cpp file. There is a section starting at line 235 as below:
// draw text if needed
CString str;
GetWindowText(str);
if (m_bShowPercent)
str.AppendFormat("%d%%", (int)((dFraction * 100.0) + 0.5));
I dont understand the AppendFormat method, I could not find such call for CString class, so I changed the line to the following:
str.Format(L"%d%%", (int)((dFraction * 100.0) + 0.5));
//removed the Append word and added a L to "%d%d"
It worked wonderfully under VS2005
Additionally, if anyone will be customizing this further, it would be nice to have a method to allow a bouncing progress bar, sort of modified marquee style so it bounces back.
Any helpful comments will be appreciated - otherwise thanks for sharing this with everyone.
dev75040 - Victor
dev75040@yahoo.com
|
|
|
|
 |
|
 |
I believe the problem you had in VS2005 was that you were compiling for Unicode. There was a bug in the program in the AppendFormat line. There is an _T() macro missing around the format string. The line should read:
str.AppendFormat(_T("%d%%"), (int)((dFraction * 100.0) + 0.5));
If yo change the AppendFormat to a plain Format, the fixed text option won't work anymore.
AppendFormat is a method of the CStringT class.
|
|
|
|
 |
|
 |
The demo project is still showing the old / previous version of the Progress Control with Text. Can you update it to the new version?
Thanks, André
|
|
|
|
 |
|
 |
All fixed - sorry about that
cheers,
Chris Maunder
CodeProject.com : C++ MVP
|
|
|
|
 |
|
 |
Thanks,
There is still one problem with the demo-project. They didn't load in my VS.NET2003 environment. I solved it by picking up the '.VSNET2002'- file, change it to '.sln'. Then editing this one and the project-file directly and change '8.00' to '7.10'.
It's now working!
thanks again,
André
|
|
|
|
 |
|
 |
would it have been possible to use ExtTextOut to render the text, just changing the lpRect param to control the clipping (+ ETO_CLIPPED of course)?
this is not a criticism, its just that i've not tried it before and wondered if anyone else had.
.dan.g.
AbstractSpoon Software
abstractspoon2_at_optusnet_dot_com_dot_au
|
|
|
|
 |
|
 |
Probably! I've not tried it either.
Anyone got some spare time to play?
cheers,
Chris Maunder
CodeProject.com : C++ MVP
|
|
|
|
 |
|
 |
ExtTextOut will work to render the text. That is how the newly posted version got the vertical text display to work. The original code used DrawText and that function doesn't support text output with an escapement and orientation different than zero degrees.
TonyB
|
|
|
|
 |
|
 |
It's simple and useful, thanks chris smart work.
liansp
|
|
|
|
 |
|
 |
Hi Chirs,
Any chance you can update this to use XP themes?
|
|
|
|
 |
|
 |
Hello all,
What a pity nobody answered this question because it would have saved me some work. Never mind, I worked out how to do the Theme support myself and will share it with you. Five easy steps:
1) Study the classes CXPStyleButtonST and CButtonST very carefully. What you will find is that the OnPaint() function in ButtonST calls a virtual function OnDrawBackground() that does the actual drawing. In CXPStyleButtonST this function is overwritten to do the themed drawing. The themed drawing uses a helper class called CThemeHelperST that tabs into the windows theme DLL.
2) In order to support a themed progress bar we will create a new class, CXPStyleProgress that derives from CTextProgressCtrl.
3) In CTextProgressCtrl, split up the OnPaint() so that the actual owner-draw painting is done in
virtual void DrawProgressBar(CDC* pDC, CRect* pRect, double dFraction);
4) Add Theme support to CXPStyleProgress. The header file will include:
#include "TextProgressCtrl.h"
#include "ThemeHelperST.h"
Also add a theme helper pointer to the class:
private:
CThemeHelperST* m_pTheme;
public:
void SetThemeHelper(CThemeHelperST* pTheme);
In SetThemeHelper you set the theme pointer:
m_pTheme = pTheme;
5) Now add the overloaded function to CXPStyleProgress:
virtual void DrawProgressBar(CDC* pDC, CRect* pRect, double dFraction);
The complete function body:
void CXPStyleTextProgress::DrawProgressBar(CDC* pDC, CRect* pRect, double dFraction)
{
BOOL bDefaultDraw = FALSE;
// No theme helper passed
if (m_pTheme == NULL || m_pTheme->IsAppThemed() == FALSE)
{
bDefaultDraw = TRUE;
} // if
else
{
HTHEME hTheme = NULL;
int iStateId = 0;
hTheme = m_pTheme->OpenThemeData(GetSafeHwnd(), L"PROGRESS");
if (hTheme)
{
// Set up the rectangles. The left one is filled, the right one empty (white)
CRect LeftRect, RightRect, ClientRect;
ClientRect = *pRect;
ClientRect.DeflateRect( 4 /* x */, 3 /* y */); // leave space for the borders
LeftRect = RightRect = ClientRect;
//
// Draw borders and progress bar
//
#ifdef PBS_VERTICAL
DWORD dwStyle = GetStyle();
if (dwStyle & PBS_VERTICAL)
{
// calculate the exact bar and chunk positions for vertical progress
LeftRect.top = LeftRect.bottom - (int)((LeftRect.bottom - LeftRect.top) * dFraction);
RightRect.bottom = LeftRect.top;
// draw the bar and chunk
m_pTheme->DrawThemeBackground(hTheme, m_hWnd, pDC->GetSafeHdc(), PP_BARVERT, iStateId, pRect, NULL);
m_pTheme->DrawThemeBackground(hTheme, m_hWnd, pDC->GetSafeHdc(), PP_CHUNKVERT, iStateId, &LeftRect, NULL);
}
else
#endif
// horizontal drawing
{
// calculate the exact bar and chunk positions for horizontal progress
LeftRect.right = LeftRect.left + (int)((LeftRect.right - LeftRect.left)* dFraction);
RightRect.left = LeftRect.right;
// draw the bar and chunk
m_pTheme->DrawThemeBackground(hTheme, m_hWnd, pDC->GetSafeHdc(), PP_BAR, iStateId, pRect, NULL);
m_pTheme->DrawThemeBackground(hTheme, m_hWnd, pDC->GetSafeHdc(), PP_CHUNK, iStateId, &LeftRect, NULL);
}
//
// Draw themed text (horizontal only)
//
int iTextLength = m_strText.GetLength();
if (iTextLength > 0)
{
TCHAR *pszText = new TCHAR[iTextLength+1];
_tcscpy(pszText, m_strText);
int widelen = MultiByteToWideChar(CP_ACP, 0, pszText, iTextLength+1, NULL, 0);
WCHAR *pszWideText = new WCHAR[widelen+1];
MultiByteToWideChar(CP_ACP, 0, pszText, iTextLength, pszWideText, widelen);
SetBkMode(pDC->GetSafeHdc(), TRANSPARENT);
m_pTheme->DrawThemeText(hTheme,
pDC->GetSafeHdc(),
PP_BAR,
0,
pszWideText,
iTextLength,
DT_CENTER | DT_VCENTER | DT_SINGLELINE,
NULL,
ClientRect);
}
m_pTheme->CloseThemeData(hTheme);
} // if
else
{
bDefaultDraw = TRUE;
} // else
} // else
if (bDefaultDraw)
{
return CTextProgressCtrl::DrawProgressBar(pDC, pRect, dFraction);
} // if
}
Some remarks:
This themed drawing only supports horizontal text drawing. I do not need vertical text drawing myself so I'll leave it as an excercise for someone else.
I use themed text drawing with something like DrawThemeText(). Alternatively you can use pDC->DrawText() but I think that it is better not to 'mix and match' themed drawing and DC drawing. I tried it and was unhappy with the results: sometimes the text did not redraw properly after 'wiping over' the progress control with another dialog.
Hope this helps.
Hidde Wallaart
software engineer
|
|
|
|
 |
|
 |
I'm also adding XP styles support to this, I've noticed some bugs in your code.
Char conversion is too complicated and does not free allocated memory.
I've used ATL's conversion:
USES_CONVERSION;
WCHAR *pszWideText = T2W(str);
Your should use something like this to find proper border size of the progress:
GetThemeBackgroundContentRect(dc,PP_BAR,0,ClientRect,chunkRect);
The problem with text is that it's not comfortable to see above XP style chunk
rrrado
|
|
|
|
 |
|
 |
Hi, Chris
Is very Good, this Control.
I have detect one problem, when I call function
SetRange32(0, 0)
The CPU is 100%.
If I comment:
void CTextProgressCtrl::OnPaint()
{
//if (m_nMin >= m_nMax)
// return;
...
}
Not occur ???.
|
|
|
|
 |
|
 |
The OnPaint() handler should have the CPaintDC moved to be the first line
of the routine, ie, from this
void CTextProgressCtrl::OnPaint()
{
if (m_nMin >= m_nMax)
return;
CPaintDC PaintDC(this); // device context for painting
....
to this
void CTextProgressCtrl::OnPaint()
{
CPaintDC PaintDC(this); // device context for painting
if (m_nMin >= m_nMax)
return;
....
In the code as presented, if you do happen to set the min and max values the
same the CPaintDC is never created, which means that the Win32 API
BeginPaint()/EndPaint() pair is never called, which means that an infinite
number of WM_PAINT messages are sent to the progress control. Result is upto
100% CPU usage and the application stalls
You should keep the test against m_nMin and m_nMax in place (don't just comment it out) otherwise you risk a divide-by-zero error.
|
|
|
|
 |
|
 |
Hi,
I cant get the example project to compile under VC7 (.net), also i have no idea as to what the problem is as im to inexperienced to understand!
The compiler throws these errors:
c:\Documents and Settings\Joe\Desktop\text_progressctrl_demo\TextProgressCtrl.cpp(157): error C2440: 'static_cast' : cannot convert from 'LRESULT (__thiscall CTextProgressCtrl::* )(UINT,LPCTSTR)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
c:\Documents and Settings\Joe\Desktop\text_progressctrl_demo\TextProgressCtrl.cpp(158): error C2440: 'static_cast' : cannot convert from 'LRESULT (__thiscall CTextProgressCtrl::* )(UINT,LPTSTR)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
c:\Documents and Settings\Joe\Desktop\text_progressctrl_demo\TextProgressCtrl.cpp(165): error C2440: 'static_cast' : cannot convert from 'void (__thiscall CTextProgressCtrl::* )(WPARAM,LPARAM)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
c:\Documents and Settings\Joe\Desktop\text_progressctrl_demo\TextProgressCtrl.cpp(166): error C2440: 'static_cast' : cannot convert from 'void (__thiscall CTextProgressCtrl::* )(WPARAM,LPARAM)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
c:\Documents and Settings\Joe\Desktop\text_progressctrl_demo\TextProgressCtrl.cpp(170): error C2440: 'static_cast' : cannot convert from 'void (__thiscall CTextProgressCtrl::* )(WPARAM,LPARAM)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
Any ideas?
Joe
#
|
|
|
|
 |