Re: Draw Image Using 2D Byte Array ?
Hi,
I'm used MFC Dialog, Both InvalidateRect(WindowHandle, NULL, false); & UpdateWindow(WindowHandle); commands are not working. WindowHandle means? & also arguments size are vary in that method.
In my application, I'm getting continuous data from the OnTimer() Method & shake the window to plot the data.
B'cos I don't know how to call the Paint method?
Re: Draw Image Using 2D Byte Array ?
1. In MFC you usually use MFC methods:
CWnd::InvalidateRect or CWnd::Invalidate
CWnd::UpdateWindow
2. You never "call the Paint method" yourself! It is called by Windows as a response to your Invalidate or InvalidateRect calls.
1 Attachment(s)
Re: Draw Image Using 2D Byte Array ?
Hi Mr.Victor,
I read the CWnd::InvalidateRect page from MSDN.
But flickering occurred while using the command.
Code:
CRect rect;
rect.left = 0;
rect.top = 0;
rect.right = ClientWidth; //1000
rect.bottom = ClientHeight;//256
InvalidateRect(rect,1); //Refresh the area only but flickering occurred & buttons hidden if any other window appear.
//InvalidateRect(rect,0);// If any other window appear buttons are hidden.
Please find the attachment and replace the .cpp from Dave.rar.
Am I correct? or wrongly used the code?
Please clear me. Waiting for your reply.
Re: Draw Image Using 2D Byte Array ?
I used the command like below,
Now, Flickering occurred the particular area (0, 0 ,1000, 256).
Code:
CRect rect;
rect.left = 0;
rect.top = 0;
rect.right = ClientWidth; //1000
rect.bottom = ClientHeight;//256
InvalidateRect(&rect);
How can i draw an image without flickering?
Anybody Please give an idea to solve my problem.
Re: Draw Image Using 2D Byte Array ?
What interval did you set in your SetTimer call?
Re: Draw Image Using 2D Byte Array ?
Quote:
Originally Posted by
saraswathisrinath
I used the command like below,
Now, Flickering occurred the particular area (0, 0 ,1000, 256).
Code:
CRect rect;
rect.left = 0;
rect.top = 0;
rect.right = ClientWidth; //1000
rect.bottom = ClientHeight;//256
InvalidateRect(&rect);
You missed to add a note that you do this InvalidateRect inside WM_PAINT handler. That is definitely a bad idea, as you make the system never stop with refreshing. Please explain what you tried to achieve with that.
Quote:
How can i draw an image without flickering?
You prepare your bitmap bits first, and only then you invalidate the paint area. The paint must be done in minimum of calculations, a single blit is preferable. The process of refreshing must be driven by some mechanism separate from WM_PAINT handler, thread maybe, or timer routine for example.
Re: Draw Image Using 2D Byte Array ?
Quote:
Originally Posted by
Igor Vartanov
You missed to add a note that you do this InvalidateRect inside WM_PAINT handler.
Good catch. Igor!
I missed it (just thought InvalidateRect is called from within the WM_TIMER handler) :(
Re: Draw Image Using 2D Byte Array ?
You may see flickering when Windows erases the client area, that is, sets all of the pixels in the client area to the window's class's background brush color. To prevent Windows from doing this, you need to capture the WM_ERASEBKGND message so that it does not reach the default window procedure. According to MFC documentation, you do this by overriding the OnEraseBkgnd() method. However, if another window is moved around on top of your window, Windows will still erase the other window with your window's class's background brush color. To prevent this, set your window's class's background brush to NULL_BRUSH when the window's class is created.
Code:
Window.hbrBackground = HBRUSH(GetStockObject(NULL_BRUSH));
But since you are not creating your window's class from scratch, you may not be able to do this.
As Igor noted, you should be updating your image and calling the InvalidateRect() function from inside your OnTimer() method.
Also, the flickering could be caused by your monitor. I have two monitors. The test application, that I wrote and have since added a timer event to scroll the image vertically, flickers a little on one of my monitors but not on the other.
Re: Draw Image Using 2D Byte Array ?
I used the InvalidateRect Command in OnPaint of method on my 18th Post.
But, Today post, I used the InvalidateRect method inside the OnTimer method only.
so only I recover my project from Hidden controls problem.
I call the timer at every 40 millisec for see the real time data like moving.
I'm getting the real time data in OnTimer method at the same time, inside timer I was used the InvalidateRect command.
But flickering occurred in the defined rect. If I increase the timer 1000 instead of 40 millisec means it will reduce (Flickering).
Sorry I was only not define correctly my post.
Re: Draw Image Using 2D Byte Array ?
Well, if you let your image change every 40 millisec then flickering must occur!
But does your image really change every 40 millisec?
Re: Draw Image Using 2D Byte Array ?
Mr.Dave, I will see the flickering when Windows erases the client area. I accept this.
If I set the background color means I recover my project from this problem?
Mr.Victor, I have the same doubt, Now only I start to test my project that how many times paint method call for set the timer = 40 millisec.
I will come back soon & reply.
Re: Draw Image Using 2D Byte Array ?
I forgot to mention that when you call the InvalidateRect() function, set the bErase parameter to FALSE so that the WM_ERASEBKGND message does not get sent to the window.
Are you having a "hidden controls" problem? If you have controls or text on the client area and you are redrawing the entire client area with the image using code like the following,
Code:
for (y = 0; y < ClientHeight; y = y + 1)
{
Index = y * NumberOfBytesPerRow;
for (x = 0; x < ClientWidth; x = x + 1)
{
ImageData[Index] = y;
Index = Index + 1;
}
}
then you are drawing over the controls and text.
1 Attachment(s)
Re: Draw Image Using 2D Byte Array ?
Quote:
Originally Posted by
Coder Dave
I forgot to mention that when you call the InvalidateRect() function, set the bErase parameter to FALSE so that the WM_ERASEBKGND message does not get sent to the window.
This hint really works good. Really very happy :) Thank to all Guru's.
Code:
BOOL CDaveDlg::OnEraseBkgnd(CDC* pDC)
{
if(refreshflag == false)
{
CRect rcClient;
GetClientRect(&rcClient);
if((HBRUSH)brush == NULL)
brush.CreateSolidBrush(MYCOLOR); //0,0,0
pDC->FillRect(&rcClient, &brush);
brush.DeleteObject();
}
else
{
return false;
}
return true;
}
HBRUSH CDaveDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
pDC->SetBkColor(MYCOLOR);
pDC->SetTextColor(RGB(128,64,0));
if((HBRUSH)brush == NULL)
brush.CreateSolidBrush(RGB(0,0,0));
return (HBRUSH) brush;
}
Using the above code, I recover my project from flickering now. But I can't to display the dialog background now.
Kindly find the attachment. The code works like that only for dialog background.
Is possible to set the background for dialog ? But, that code won't affect the image display?
Pls clear me.
Re: Draw Image Using 2D Byte Array ?
Quote:
Originally Posted by
saraswathisrinath
Is possible to set the background for dialog ? But, that code won't affect the image display?
WM_CTLCOLORDLG returns a brush. This is your dialog's background. The brush may be a solid color brush, some stock object (standard Windows brush), a bitmap based brush, etc. All further painting is done over the background.
Re: Draw Image Using 2D Byte Array ?
Quote:
Originally Posted by
saraswathisrinath
Using the above code, I recover my project from flickering now. But I can't to display the dialog background now.
I think I understand your problem now. We do not want the dialog to redraw its background where the image is, since this causes flickering and is inefficient. However, we can not stop the dialog from redrawing the background behind the image without stopping it from redrawing the background all together. The solution is to write your own code to draw the background where the image is not present.
I have never used the CDialog class, so I do not know how much it is doing behind the scenes. If this was just a regular window that you created from scratch, you would draw the dialog background and the controls that go on top of it in the WM_PAINT event. Of course, you would still use BitBlt() in the WM_PAINT event to display the image.
Alternatively, you could create your bitmap so that it takes up the whole client area. Then, part of the bitmap would be used to draw your image and the other part would be used to draw your text and other controls. If you draw on the bitmap's compatible device context with the GDI functions, your text and controls will be drawn onto the bitmap. Then all you would need to do in your OnPaint() method is to use BitBlt() on the entire client area. Your OnEraseBkgnd() method should do nothing except return true.
Now, I see some problems with your code:
Code:
BOOL CDaveDlg::OnEraseBkgnd(CDC* pDC)
{
if(refreshflag == false)
{
CRect rcClient;
GetClientRect(&rcClient);
if((HBRUSH)brush == NULL)
brush.CreateSolidBrush(MYCOLOR); //0,0,0
pDC->FillRect(&rcClient, &brush);
brush.DeleteObject();
}
else
{
return false;
}
return true;
}
Do not create a brush object in any event the will be called over and over again. Instead, create the brush in the create event and save the handle somewhere so that other events can access it. Delete the brush object in the destroy event. Also, your code above has an error. Since you do not set the brush handle to NULL after you delete it, the next time the code is executed, it will try to fill the rectangle with an invalid brush handle.