|
transparent color |
Posted by Alex on May-19-2024 03:26 |
|
Hello dear developer! First of all thank you for the greatest library it is very usefull and very convinient!!! I am using the C++ version (7.0). I attached the screenshot of my final control and show the black zones with a red arrow i want to make a fully transparent against my back color of my main dialog. Is it possible to make that zones transparent? could you please give me some tips how to do that (code snippet would be appreciated)!!!
Here is a code of my control:
void CsdkDemoDlg::drawSpeedMeter(CChartViewer* viewer, double pointer_value, CString label1)
{
int chartIndex = 3;// индекс в массиве mainColor, устанавливаем основной цвет
// The main color of the four meters in this example. The other colors and gradients are derived
// from the main color.
int colorList[] = { 0x007700, 0x770077, 0x0033dd, RGB(environment_b, environment_g, environment_r) };
int mainColor = colorList[chartIndex];
//
// In this example, we demonstrate how to parameterized by size, so that the chart size can be
// changed by changing just one variable.
//
float scale = min(scalefactor.x, scalefactor.y);
int size = 500 * scale;
// The radius of the entire meter, which is size / 2, minus 2 pixels for margin
int outerRadius = size / 2 - 2;
// The radius of the meter scale
int scaleRadius = outerRadius * 92 / 100;
// The radius of the inner decorative circle
int innerRadius = scaleRadius * 40 / 100;
// The width of the color scale
int colorScaleWidth = scaleRadius * 10 / 1000;
// Major tick length
int tickLength = scaleRadius * 10 / 100;
// Major tick width
int tickWidth = scaleRadius * 1 / 100 + 1;
// Label font size
int fontSize = scaleRadius * 13 / 100;
//
// Create an angular meter based on the above parameters
//
// Create an AngularMeter object of the specified size. In this demo, we use black (0x000000) as
// the background color. You can also use transparent or other colors.
//m = new AngularMeter(size, size, 0x000000);
AngularMeter* m = new AngularMeter(size, size, Chart::Transparent);
//m->setWallpaper("data/matrix.jpg");
// Set the default text and line colors to white (0xffffff)
m->setColor(Chart::TextColor, RGB(text_b, text_g, text_r));
m->setColor(Chart::LineColor, RGB(environment_b, environment_g, environment_r));
// Set meter center and scale radius, and set the scale angle from -180 to +90 degrees
m->setMeter(size / 2, size / 2, scaleRadius, -140, 140);
// Background gradient with the mainColor at the center and become darker near the border
double bgGradient[] = { 0, (double)(mainColor), 0.5, (double)(m->adjustBrightness(mainColor, 0.75
)), 1, (double)(m->adjustBrightness(mainColor, 0.15)) };
// Fill the meter background with the background gradient
m->addRing(0, outerRadius, m->relativeRadialGradient(DoubleArray(bgGradient, (int)(sizeof(
bgGradient) / sizeof(bgGradient[0]))), outerRadius * 0.66));
// Fill the inner circle with the same background gradient for decoration
m->addRing(0, innerRadius, m->relativeRadialGradient(DoubleArray(bgGradient, (int)(sizeof(
bgGradient) / sizeof(bgGradient[0]))), innerRadius * 0.8));
// Gradient for the neon backlight, with the main color at the scale radius fading to
// transparent
double neonGradient[] = { 0.89, Chart::Transparent, 1, (double)(mainColor), 1.07,
Chart::Transparent };
m->addRing(scaleRadius * 85 / 100, outerRadius, m->relativeRadialGradient(DoubleArray(
neonGradient, (int)(sizeof(neonGradient) / sizeof(neonGradient[0])))));
// The neon ring at the scale radius with width equal to 1/80 of the scale radius, creating
// using a brighter version of the main color
m->addRing(scaleRadius, scaleRadius + scaleRadius / 80, m->adjustBrightness(mainColor, 2));
// Meter scale is 0 - 100, with major/minor/micro ticks every 10/5/1 units
m->setScale(0, 100, 10, 5, 1);
// Set the scale label style, tick length and tick width. The minor and micro tick lengths are
// 80% and 60% of the major tick length, and their widths are around half of the major tick
// width.
m->setLabelStyle("arialb.ttf", fontSize);
m->setTickLength(-tickLength, -tickLength * 80 / 100, -tickLength * 60 / 100);
m->setLineWidth(0, tickWidth, (tickWidth + 1) / 2, (tickWidth + 1) / 2);
m->setMeterColors(RGB(text_b, text_g, text_r), RGB(text_b, text_g, text_r), RGB(text_b, text_g, text_r));// цвета цифр скорости и делений
// Demostrate different types of color scales and glare effects and putting them at different
// positions.
double smoothColorScale[] = { 0, 0x0000ff, 25, 0x0088ff, 50, 0x00ff00, 75, 0xdddd00, 100,
0xff0000 };
double stepColorScale[] = { 0, 0x00dd00, 30, 0xddaa00, 70, 0xdd0000, 100 };
double highColorScale[] = { 70, Chart::Transparent, 100, 0xff0000 };
if (chartIndex == 1) {
// Add the smooth color scale just outside the inner circle
m->addColorScale(DoubleArray(smoothColorScale, (int)(sizeof(smoothColorScale) / sizeof(
smoothColorScale[0]))), innerRadius + 1, colorScaleWidth);
// Add glare up to the scale radius, concave and spanning 190 degrees
m->addGlare(scaleRadius, -190);
}
else if (chartIndex == 2) {
// Add the high color scale at the default position
m->addColorScale(DoubleArray(highColorScale, (int)(sizeof(highColorScale) / sizeof(
highColorScale[0]))));
// Add glare up to the scale radius
m->addGlare(scaleRadius);
}
else {
// Add the step color scale just outside the inner circle
m->addColorScale(DoubleArray(stepColorScale, (int)(sizeof(stepColorScale) / sizeof(
stepColorScale[0]))), innerRadius + 1, colorScaleWidth);
// Add glare up to the scale radius, concave and spanning 190 degrees and rotated by -45
// degrees
//m->addGlare(scaleRadius, -190, -45);
}
if (pointer_value <= 31)
{
// Add a red (0xff0000) pointer at the specified value
m->addPointer2(pointer_value, 0x00dd00);
}
if (pointer_value >= 31 && pointer_value <= 71)
{
// Add a red (0xff0000) pointer at the specified value
m->addPointer2(pointer_value, 0xddaa00);
}
if (pointer_value >= 71 && pointer_value <= 101)
{
// Add a red (0xff0000) pointer at the specified value
m->addPointer2(pointer_value, 0xdd0000);
}
// Set the cap background to a brighter version of the mainColor, and using black (0x000000) for
// the cap and grey (0x999999) for the cap border
m->setCap2(m->adjustBrightness(mainColor, 1.1), Chart::Transparent, Chart::Transparent);
// Add a text label коробка скоростей centered at (250, 410) with 20pt Arial Bold font
if (label1 == "L")
{
m->addText(250 * scale, 410 * scale, label1, "arialbd.ttf", 20 * min(scalefactor.x, scalefactor.y), 0x00dd00, Chart::Center);
}
if (label1 == "D")
{
m->addText(250 * scale, 410 * scale, label1, "arialbd.ttf", 20 * min(scalefactor.x, scalefactor.y), 0xddaa00, Chart::Center);
}
if (label1 == "T")
{
m->addText(250 * scale, 410 * scale, label1, "arialbd.ttf", 20 * min(scalefactor.x, scalefactor.y), 0xdd0000, Chart::Center);
}
// Add a text label еденицы измерения centered at (250, 320) with 15pt Arial Italic font
if (label1 == "L")
{
m->addText(250 * scale, 320 * scale, "km/h", "arialb.ttf", 15 * min(scalefactor.x, scalefactor.y), 0x00dd00, Chart::Center);
}
if (label1 == "D")
{
m->addText(250 * scale, 320 * scale, "km/h", "arialb.ttf", 15 * min(scalefactor.x, scalefactor.y), 0xddaa00, Chart::Center);
}
if (label1 == "T")
{
m->addText(250 * scale, 320 * scale, "km/h", "arialb.ttf", 15 * min(scalefactor.x, scalefactor.y), 0xdd0000, Chart::Center);
}
// Output the chart
viewer->setChart(m);
//free up resources
delete m;
}
Thank you!!!
|
Re: transparent color |
Posted by Peter Kwan on May-20-2024 19:12 |
|
Hi Alex,
The meter background color are specified with the following code:
double bgGradient[] = { 0, (double)(mainColor), 0.5, (double)(m->adjustBrightness(mainColor, 0.75
)), 1, (double)(m->adjustBrightness(mainColor, 0.15)) };
// Fill the meter background with the background gradient
m->addRing(0, outerRadius, m->relativeRadialGradient(DoubleArray(bgGradient, (int)(sizeof(
bgGradient) / sizeof(bgGradient[0]))), outerRadius * 0.66));
// Fill the inner circle with the same background gradient for decoration
m->addRing(0, innerRadius, m->relativeRadialGradient(DoubleArray(bgGradient, (int)(sizeof(
bgGradient) / sizeof(bgGradient[0]))), innerRadius * 0.8));
Basically, you just need to adjust the colors and other gradient parameters (like the various radii) until you get the effect you want. You can use Chart::Transparent for some color stops for the gradient.
I tried the change the code to the following, and it can draw something similar to you mentioned.
double bgGradient[] = { 0, Chart::Transparent, 0.4, mainColor, 1.1, Chart::Transparent };
const int bgGradient_size = (int)(sizeof(bgGradient) / sizeof(*bgGradient));
// Fill the meter background with the background gradient
m->addRing(innerRadius, outerRadius, m->relativeRadialGradient(DoubleArray(bgGradient, bgGradient_size),
outerRadius * 0.8));
// Fill the inner circle with the same background gradient for decoration
m->addRing(0, innerRadius, m->relativeRadialGradient(DoubleArray(bgGradient, bgGradient_size), innerRadius * 0.8));
Best Regards
Peter Kwan |
Re: transparent color |
Posted by Alex on May-21-2024 02:10 |
|
Peter, Thank you very much for a quick reply!!! Code you posted exactly what i need, perfect!!! But i have some troubles with redraw animation, if i use the code as it is and invoke the drawSpeedMeter(CChartViewer* viewer, double pointer_value, CString label1) function with "pointer" value changing it looks like (attached picture 1), but if i make the following change in code: m->setWallpaper("data/matrix.jpg");, and set the background as a wallpaper everything is ok. For some reason i need to draw some custom stuff on the background and i don't want to set the static Wallpaper as a background color. Is it possible to avoid setting the wallpaper background and still using the transparent zones of the control during arrow animation ?
Here is a picture 1 without m->setWallpaper:
|
Re: transparent color |
Posted by Alex on May-21-2024 02:11 |
|
Here is a picture 2 with m->setWallpaper as a background:
|
Re: transparent color |
Posted by Peter Kwan on May-21-2024 17:00 |
|
Hi Alex,
I have just tried myself. It works normally in my case. I have attached the complete Visual Studio project for your reference. To try it, starting from ChartDirector 7, please replace the original helloworld sample code in "ChartDirector/mfcdemo/helloword" with the "helloworld" folder in the download. Then compile and run helloword. It is a real time semi-transparent meter that updates once per second on a window with a wallpaper background, and it works normally.
https://www.advsofteng.com/support/mfc_transparent_meter.zip
The issue in your case is likely because the chart is redrawn without erasing and redrawing the background first.
You may think the background wallpaper and the chart are two separate things, and when you remove the chart, you can see the wallpaper. This is an illusion. The only thing that exists are the pixels on the window. When you put anything over the background, the background pixels are overwritten with whatever you draw. The original background pixels are lost forever.
If you cover the background with a semi-transparent object, the pixels are overwritten by a blend of the background and the object. You can think the background color is "diluted" by the foreground color. If you paint the foreground again, the background will dilute further until you can longer see the background color.
To prevent this, MFC should automatically erase the background and repaint the background before allowing the control to update. That's why it works in my project.
However, if your "background" is not really the window background, but is a different control (eg. a picture control with an image) put under the chart, then you would need to repaint everything yourself from the bottom up.
Best Regards
Peter Kwan |
Re: transparent color |
Posted by Alex on May-22-2024 17:52 |
|
Hi, Peter! Thank you very much for explanation and complete VS project. I use CMFCPropertyPage instead of CDialog as a backgroud for CChartViewer control, but hehaviour are the same (CMFCPropertyPage is derived from CDialog as far as i know). I made some changes in my project and added OnEraseBkgnd message handler, in my current version of CChartViewer my project is based on example you provided doesn't work. After i replaced ChartViewer.cpp and ChartViewer.h with your version of files transparent meter started to work as expected, but i have some troubles with drawing speed and stability (some times my project crushes during the meter redraw) also other controls based on chartdir library started to drawn with wrong resolution.
My question: is it possible to make the transparent meter example to work with my current version of ChartViewer (2016)? I've attached the files.
|
Re: transparent color |
Posted by Peter Kwan on May-23-2024 23:20 |
|
Hi Alex,
Sorry I forgot to mention about the version. The CChartViewer I am using is from ChartDirector 7. It may not work with older versions of ChartDirector DLL.
I added the OnEraseBkgnd in my test code because it is the only method I can think of that can draw a background wallpaper. If you have other methods to draw a background wallpaper, you can freely that as well. It does not matter. The only requirement is it is really a "background", and that the window is the parent of the CChartViewer.
(In Windows, "background" means the graphics that is drawn in the device context provided by the WM_ERASEBKGND message in the message handler. MFC has a default implementation that draws a solid color. In my code, I override it to draw a bitmap repeatedly. There may be other methods that can draw a "background" that I am not aware of.)
In previous versions of ChartDirector, you have to repaint the "background" with your own code immediately before ChartDirector draws the chart with no other GUI message in between, otherwise the screen will flicker. The best method is to override the OnPaint method of the CChartViewer so that you code can repaint background first immediately before ChartDirector paints the chart.
For static background, I think it is easier to simply use the same wallpaper as both the background of the window and as the background of the chart. I assume your code must have the wallpaper image, so it should not be difficult to generate one suitable as the chart background. The "override OnPaint" method is more general and it works even if the background is dynamic and updated in real time.
Best Regards
Peter Kwan |
Re: transparent color |
Posted by Alex on May-24-2024 19:15 |
|
Hi Peter,
I think the best way for me is to use setWallpaper() method. Thank you for help. Question is solved. |
|