How do I do this so that I select which Picture control I want the bargraph
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
This is pretty bad code. In fact, it is really, really awful. There's
about one error
per line.
Where is this being drawn? Is OnShow called from your OnPaint handler?
If it isn't, this
whole piece of code is nearly useless.
The style is also pretty bad, and you should never "reach inside" a
control to draw it as
you do here. You can pretty much throw this code out, and save some
pieces of it for the
correct place
The correct approach is to put the body of this code in a subclassed
control (most
commonly a CStatic, for example), as
class CMyControl : public CStatic { // for example, using ClassWizard
public:
void SetValues(CByteArray b);
protected:
int units;
CByteArray values;
};
CMyControl::CMyControl()
{
}
void CMyControl::SetValues(CByteArray & b)
{
values.SetSize(0);
values.Copy(b);
Invalidate();
}
#define DIM(x) (sizeof(x) / sizeof((x)[0])
COLORREF barcolors[] = {
RGB(255, 0, 0),
RGB(0, 255, 0),
RGB(0, 0, 255),
RGB(255, 0, 255),
RGB(255, 255, 0),
RGB(0, 255, 255),
... more colors until you get bored
};
void CMyControl::OnPaint()
{
CPaintDC dc(this);
CRect r;
if(b.GetSize() == 0)
return; // array of samples is empty
GetClientRect(&r);
int dx = cr.Width() / b.GetSize();;
int leftover = cr.Width() - (dx * b.GetSize());
// because the width may not be evenly divisible by the number of
samples,
// the sum of samples will not fill in the entire window. So we
compute the
// "leftover" value which allows us to "stretch" some of the bars to
// make sure that we fill the whole area
int x = 0;
for(int i = 0; i < b.GetSize(); i++)
{ /* draw each histogram */
int saved = dc.SaveDC();
int h = ?;// compute height of histogram here
int w = dx;
if(leftover > 0)
{ /* fudge width */
w++;
leftover--;
} /* fudge width */
CBrush br(barcolors[i % DIM(barcolors)]);
dc.SelectObject(&br);
CRect r(x, r.bottom - h, x+w, r.bottom);
dc.Rectangle(r);
dc.RestoreDC(saved);
} /* draw each histogram */
}
You have to make sure the brush is not selected intot he DC when ~CBrush
is executed,
hence the SaveDC/RestoreDC calls.
To set the values, do something like
#define NUMBER_OF_SAMPLES 30
CByteArray b;
b.SetSize(NUMBER_OF_SAMPLES);
CFile f;
if(!f.Open(_T("teststring,dat"), CFile::modeRead))
... deal with error here
f.Read(b.GetData(), NUMBER_OF_SAMPLES);
f.Close();
c_MyControl.SetValues(b);
Key here is that the ONLY place you can do this drawing is in the OnPaint
handler of the
child control (or in some function called from OnPaint). It *must* have
all the
information required to do the drawing, at any arbitrary time, without
warning, and it
must be able to redraw the entire window contents.
joe
----------------------------------------------------------------------------
On Fri, 08 Sep 2006 00:47:31 GMT, "Ed" <eddie@hvc.rr.com> wrote:
I have the following code section:
void TestGraph::OnShow()
{
int a, b, c, d;
****
Avoid ever using a comma in a declaration list. If you want four
variables, declare them
as
int a;
int b;
int c;
int d;
of course, with really meaningful names like a,b,c,d it is nearly
impossible to figure out
what the code is trying to do.
in = fopen("teststring.dat", "rb");
fread(bars, 30, 1, in);
fclose(in);
CRect cr;
CBrush blk(RGB(0,0,0));
GetDlgItem(IDC_PICU1)->GetClientRect(cr);
****
This is wrong; avoid GetDlgItem. See my essay on Avoiding GetDlgItem.
Do not try to get the rectangle of some internal control from outside
itself
****
CWnd* pWnd=GetDlgItem(IDC_PICU1);
****
Do not use GetDlgItem
****
d = (cr.Width()/30);
****
Do not hardwire 30
****
pControlDC=pWnd->GetDC();
****
It is very rare to need to GetDC(); this should be avoided whenever
possible. In the rare
cases you need a DC outside the OnPaint handler, use CClientDC. Assume
that if you write
GetDC() you have made a design error [the few times it will make sense
will be obvious;
otherwise just avoid it]
****
pControlDC->SelectObject(blk);
****
Do not manipulate the DC of a control from outside the control
****
c=10;
****
And what is the magical significance of "10"?
****
for (b=0; b<30; b++)
****
30 has appeared several times. Do not do this. Use a #define
****
{
a = ((bars[b+0x30]*10)/14) + 1;
****
What is the significance of magical values like 0x30, 10, 14, and 1? I
can't quite figure
out what you are doing here. Also, the use of meaningless identifier
names like a,b,c,d
makes the code almost totally unintelligible. Use x, y for horizontal and
vertical
positions, dx and dy for delta positions horizontally and vertically, w
and h for width
and height, and other similarly useful codes.
****
pControlDC->Rectangle (c, cr.Height(), c+2, cr.Height()-a);
****
Do this in the control itself. I'm so lost trying to reverse-engineer
what you are trying
to accomplish that I'm just guessing in my rewrite
****
c+=d;
****
If the window width is not an even multiple of the number of samples, you
won't fill the
window when you add all these widths up.
}
****
I gather you are drawing a histogram, but I can't figure out what way it
is going.
****
}
The file teststring.dat contains 30 bytes data in the range of 00 to FF
This routine draws a bargraph of my data in the PICU1 box just fine.
How do I change the color of the bars???
****
Do another SelectObject of the brush
I have tried different values of CBrush with no luck.
Please direct me in the right path.
Thanks
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm