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
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.
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
// repaint the background map
// repaint the chart
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.
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.
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
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.
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.)
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.
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.
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.
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.
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.