ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Transparent Polar Charts
Posted by Ian Hammond on Mar-24-2018 18:04
Hi

I am trying to draw a wind rose on the top of a local map. I have set the chart background to Transparent. I have noticed that the text on the wind rose has become Bold and is less distinct. Also the background didn't show though until I moved the object to the edge of the display area causing the scroll bars to appear which seemed to trigger an update. I have placed an updateViewPort in the OnMove with the intent that when I move the polar chart around,  the background is refreshed but it doesn't. Could you please advise. I have attached an image file

Many thanks

  Re: Transparent Polar Charts
Posted by Ian Hammond on Mar-24-2018 22:33
After running the app for a short period of time, it seems that when transparent mode is selected it doesn't refresh the chart and continues to over-write causing concentric circles to be displayed and text over-writing text but slightly moved. I have set the chart background to transparent and the plot area background to be transparent.

  Re: Transparent Polar Charts
Posted by Peter Kwan on Mar-26-2018 03:40
Hi Ian,

Due to the limitation of MFC, if the display is "dynamic", true transparency cannot be achieved automatically by the MFC control.

In MFC, each control will paint itself to the screen. When a control paint itself to the screen, it may overwrite other controls that have already been painted on the screen.

In your case, suppose there is a chart control on top of an image control (for your map). The image control is painted first, followed by the chart. This looks good. But it may not work correct if anything changes. For example, if the map is changed, it will overwrite the chart. If the chart is changed, the chart cannot erase itself before repainting, because will then leave a "hole" in the screen. The chart cannot know what is under the chart (it can be your image or one or more of other controls) or how to paint them (all the controls can potentially change).

When one control changes, the correct method is to repaint all overlapping controls from the bottom up. GUI frameworks that support true transparency can determine which controls in the window need to be repainted when one control changes, and repaint them in the proper order. Unluckily, MFC does not do this.

For your case, you can solve problem by doing the above with your own code. It is like:

.... create chart as usual ....

// display the chart
viewer->setChart(c);

// repaint the background map
CRect rect;
viewer->GetClientRect(&rect);
backgroundMap.InvalidateRect(rect);

// repaint the chart
viewer->Invalidate();

One drawback for the above method is that if the update is fast, the screen may flicker. It is because MFC is not designed for supporting true transparency.

Regards
Peter Kwan

  Re: Transparent Polar Charts
Posted by Ian Hammond on Mar-28-2018 00:58
Hi Peter,

Many thanks. I have tried the updates as suggested but found the constant flickering to be annoying. The polar chart is a real-time display showing wind direction. Also, I'm not sure if its picking up the correct area. The top left rectangle of the screen flickers and moves when I try to move the polar chart.

  Re: Transparent Polar Charts
Posted by Ian Hammond on Mar-30-2018 18:35
Hi Peter,

I have implemented said changes as follows:

void RTWindRoseGadget::OnViewPortChanged()
{
m_RTWindChart.DrawRTWindRose(&m_RTWindRoseViewer, m_dDistance);

// repaint the background map
CRect rect;
m_RTWindRoseViewer.GetClientRect(&rect);
m_RTWindRoseViewer.ClientToScreen(&rect);

AfxGetMainWnd()->GetActiveWindow()->InvalidateRect(rect);

// repaint the chart
m_RTWindRoseViewer.Invalidate();
//UpdateTransparentBitmap(&m_bmpTarget);
}

The chart is placed on a display page with a number of different types of display gadget. I have noticed the following:

1) It flickers beneath the area of the graph gadget.
2) If I modify the properties of the gadget or move it the background turns black.

3) When the app is in data aquisition mode and data is sent to the graph gadget, it displays the data without concentric circles being displayed, but the background changes to black.

4) If the transparency is switched off the gadget updates correctly.

5) I did wonder if it were possible to copy the area of the the overlaid image and make that a background to the graph gadget and not use the transparent settings in Chart Director.

Any advice would be most appreciated. Many thanks.

  Re: Transparent Polar Charts
Posted by Peter Kwan on Mar-31-2018 02:39
Hi Ian,

I can think of a few methods, but all have some limitations.

The key issue is that MFC only supports "double buffering" of MFC controls, but not the screen. The ChartDirector CChartViewer control is double buffered, so it will not flicker on its own. However, another control can overdraw the chart on the screen before the chart is updated. As the screen is not double buffered, this causes flickering.

If your background image is not very large or the update rate is not very fast, you may consider to use the entire background image as the background image of the polar chart using BaseChart::setBgImage. See

http://www.advsofteng.com/doc/cdcpp.htm#BaseChart.setBgImage.htm

In this case, the chart will be the same size as the background image, but the actual polar chart (the "plot area") will only occupy a small part of the chart.

If you want a smaller polar chart, it should be possible to copy part of your background image and use it as the background of the polar chart. Depending on the size and type of your background image, it may not be faster than simply using the entire background image as the map. If you can ensure your background image is in 24-bit BMP format, it is easy to extract part of the image. If you just want to extract it from the screen, you would need to use MFC code, and it will be more difficult.

Regards
Peter Kwan

  Re: Transparent Polar Charts
Posted by Peter Kwan on Mar-31-2018 16:53
Hi Ian,

After further research, it seems modern Windows can double buffered the entire Window (not just the controls). We just need to set the WS_EX_COMPOSITED Windows flag to enable it.

SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED);

I my test code, I put the above in the first line of "OnInitDialog" in the sample code. Then I can just draw the chart as usual without having to "Invalidate" anything. I can move the chart by moving the control and then redraw the chart. (Just moving the control using MoveWindow does not work correctly in my case. I need to redraw the chart after MoveWindow.)

Also, as I am using another control for the background image, in the MFC Dialog editor, I have to ensure the CChatViewer is on top of the control for the background image. (I assume you already know you can press Control-D and change the z-ordering of the controls in the MFC Dialog editor.)

Hope this can help.

Regards
Peter Kwan

  Re: Transparent Polar Charts
Posted by Ian Hammond on Apr-06-2018 21:56
Hi Peter,

Sorry for the delay in responding. I have still been unable to get this to work. I was wondering if you would consider publishing your demo program so that I can compare my changes.

Regards

  Re: Transparent Polar Charts
Posted by Peter Kwan on Apr-06-2018 23:49
Attachments:
Hi Ian,

I write the code in a haste so it is quite messy. That's why I did not attach it. I have tidied it up a bit and it is as attached.

I started with the MFC "Hello World" sample code, which is a simple bar chart. I update it several times per second with random numbers, and add a button to move the chart, and the chart has a transparent background and is on top of a background image. In my computer, it does not appear to flicker.

To try the code, please replace the "helloworld" folder in the original "ChartDirector/mfcdemo" directory with the attached "helloworld" folder. Then start up the mfcdemo solution and set "helloworld" as the start up project. You can then press the "Run" button to compile and run it.

Regards
Peter Kwan
helloworld.zip
helloworld.zip

73.37 Kb

  Re: Transparent Polar Charts
Posted by Ian Hammond on Apr-08-2018 17:46
Hi Peter,

Many thanks for the demo. I have it running ok.

Regards

  Re: Transparent Polar Charts
Posted by Ian Hammond on Apr-14-2018 18:49
Hi Peter,

I would like to share with you some of my observations which has left me somewhat confused as to what is going on.

Firstly, the code I am updating is legacy code which I have decided to update with ChartDirector. The GUI is a Document area on which the user can create display gadgets of varying types one of which is my polar chart. The original implementation to simulate transparency copied the image behind the gadget area into the gadgets client area and the polar chart was drawn on top using mfc calls. When the user moved the gadget around the background was updated.

I replaced the polar drawing functionality with ChartDirector calls where my Chart area is the entire client area of the display gadget. I have set the chart transparent.
When the gadget is displayed initially, the background image of the document window shows through. I will admit that this wasn't what I expected, I thought that I should draw the image into the client area of the gadget and it would show through the chart area.

When I move the gadget, the background image remains the same as the initial image when the gadget was created. It is only when  I move the gadget which causes the scroll windows to appear does the image in the gadget update to what is covering.

The other confusing part in all of this was when I thought I needed to copy the background image to the foreground. The original functionality of this code copied the background to the foreground but the foreground copy was offset for some reason and did not align properly. This image was covered over when the gadget was initially drawn but when I moved the gadget with chart director the background functionality kicked in.

From my observations I felt that I didn't actually need this background copying functionality because ChartDirector was doing it for me except that it didn't work whilst moving the display gadget.

Also, I have set the flag you suggested in a previous email that has stopped the flickering.

It seems that there is something amiss when a chart is moved in transparent mode or I'm missing an event. Can you please advise.

Many thanks

  Re: Transparent Polar Charts
Posted by Peter Kwan on Apr-15-2018 18:52
Hi Ian,

Do you mean currently you are using the WS_EX_COMPOSITED flag, and the flickering has stopped, but the "gadget" background does not work correctly? If you do not use the WS_EX_COMPOSITED flag, there is flickering, but in does the background work correctly?

I am not too sure what is the "gadget" in your message. Is this a MFC control that acts as a container?  Is the CChartViewer control contained within the "gadget"? Or is the CChartViewer control the "gadget" itself? If the "gadget" is the container, are you moving the gadget, or are you moving the CChartViewer within the gadget? (Is MoveWindow applied to the gadget or to the CChartViewer?) This makes a difference because it determines which control receives the update messages or events, and whether the gadget and the CChartViewer is painted in two steps (if they are not the same control) or in one step.

CChartViewer only paints the non-transparent pixels of the chart to the "device context". It does not copy the background or erase the background.

With WS_EX_COMPOSITED, when the CChartViewer needs to paint itself, Windows should first ask all controls behind the CChartViewer controls to paint themselves first. This should include the windows background, then the control for the background image, then the "gadget control" on top of the background image, and finally the CChartViewer control on top of the "gadget control". Furthermore, all these will be painted on a "buffered screen" first, then copy to the real screen, so there is no flickering.

I am not sure how the "gadget control" repaint itself. Preferably, the gadget control should not paint anything. Note that many MFC control will automatically paint the background of the control unless your code overrides it.

For your case, I am not sure how the background image can move with the control. The CChartViewer itself does not paint or copy the background image. Is it possible the "gadget" copies it but does not update it as it moves?

You mentioned your original code "copied the image behind the gadget area into the gadgets client area". If you can copy the image behind the gadget area, it should be possible to copy the image into memory and then use it as the background image of the chart. One method is to use the bitmap pattern to create a "pattern color" (see BaseChart.patternColor) and use it as the background color (see BaseChart.setBackground). In this way, the chart does not even need to be transparent.

Regards
Peter Kwan

  Re: Transparent Polar Charts
Posted by Ian Hammond on Apr-17-2018 18:02
Hi Peter,

In response to your previous replay:

1) Use of WS_EX_COMPOSITED: The flag did not affect the displayed background. IT only seemed to prevent the flickering I was experiencing. Once you move the gadget from its initial position the background image is frozen until you trigger either the vertical or horizontal scroll then it refreshes.

2) The display gadget is a CWnd container in which the CChartViewer is created.

3) I move the gadget across the  Document frame which generating the OnMove event.

4) The OnPaint function does contain code to update the client area of the display gadget, but I have since commented this out to try and isolate the effects of the ChartViewer. I'm not sure why you are suggesting that OnPaint shouldn't do anything.

5) I removed chartviewer from the display gadget to see what happens in the background. This is how I noticed that the initial background image was different to when the chartviewer was displayed. Without ChartVIewer image is slightly misaligned but when  chartviwer is displayed the image is alighned.

6) With the OnPaint code enabled the background image was being updated dutring the move, but as stated previously this was misaligned.

When the display gadget was initially created  and when you triggered the scroll bars which refreshed the background image (using chartviewerin the display gadget) the background image was displayed correctly. From this (perhaps wrongly) I wondered if I actually needed the original background capture code but for some reason chartviweer wasn't refreshing whilst the gadget was been moved. This led me to commenting out this code to see what the effects of just using chartviewer. In this istuation I wasn't expecting anything to be displayed.

I hope these comments explain my confusion of how chartviewer deals with the background.

Regards

  Re: Transparent Polar Charts
Posted by Peter Kwan on Apr-18-2018 03:22
Hi Ian,

There is no background capture code in CChartViewer. (The CChartViewer.cpp source code is included in the project and you can verify it does not capture the background.) The only thing it does is to draw the chart.

When you move the gadget, it is quite possible the Windows operating system will just copy the screen region of the gadget (which includes the background) and move it. After moving the gadget, this will leave a "hole" so Windows will ask the background object to repaint the hole, but it may not ask the gadget (or anything inside it) to repaint. That is why the background appears to move with the gadget.

In my sample code, after the CChartViewer is moved, it immediately redraw the chart. For your reference, the following is my sample code to move the CChartViewer.

    rect.left += 1;
    m_ChartViewer.MoveWindow(&rect);
    drawChart();

The redrawing false Windows to also ask the CChartViewer to repaint, so the background will not move with it.

Have your code redrawn the chart when it moves the gadget?

For your case, as there is an additional gadget CWnd, I am not sure if it also needs to invalidate and update the "gadget" CWnd itself, or just the chart.

Another thing to try is the WS_EX_COMPOSITED flag. Is this flag applies to the top level Window or to the gadget CWnd. May be you can try to apply the flag to both to see if it makes any difference.

Regards
Peter Kwan