-
[RESOLVED] Draw Image Using 2D Byte Array ?
Hi,
I like to Draw an Image Using two dimensional byte array[512][256].
I used SetPixelV method to plot the image.
But Its very slow & hidden some buttons(Controls) at run time in the same dialog.
For reference i send some code,
Code:
for(row = 0; row <512; row ++)
{
for(col = 0; col < 256; col++)
{
Data[row][col] = y;
SetPixelV(d, 10+row, 10+col, RGB(Data[row][col],Data[row][col],Data[row][col]));
}
}
pls, clear me a better solution.
-
Re: Draw Image Using 2D Byte Array ?
I'm helpless now. Any body please help me.
This is heart of my project.
-
Re: Draw Image Using 2D Byte Array ?
Setpixel calls is slow, it's a bad way to do pretty much anything.
what you want to do is create a memory bitmap, and then access the bytes of the bitmap directly.
Have a look at CreateDIBSection() and/or GetDIBits() on MSDN
-
Re: Draw Image Using 2D Byte Array ?
-
Re: Draw Image Using 2D Byte Array ?
BitBlt function
Quote:
The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.
To make it short, BitBlt transfers source DC bitmap bits to destination DC. Which means, you must have an already formed bitmap in source DC prior to blitting one.
Yet again, refer to CreateDIBSection
A DIBSection wrapper for Win32 and WinCE
By Chris Maunder, 22 May 2001
-
Re: Draw Image Using 2D Byte Array ?
Thanks a lot Mr.OReubens & Mr.Igor . I will study the above link and come back.
-
Re: Draw Image Using 2D Byte Array ?
Oh the agony of SetPixel()! I used it too, back when I did not know any better. It took about 1200 clock cycles to plot one pixel! :eek:
Like it was mentioned above, you need to call CreateDIBSection() to create a bitmap object. CreateDIBSection() allocates a one dimensional array to hold the image data. In the following code samples below, I have created my own structures that have more meaningful attribute names. You should be able to figure out what the official attribute names are. Also, the variable ImageData points to an array of unsigned ints.
Code:
// Create a bitmap object.
DeviceContextHandle = NULL;
ImageData = NULL;
NumberOfDoubleWordsPerImageRow = ((ImageWidth + 1) * 3) >> 2;
BitmapHeader.HeaderSize = sizeof(bitmap_header);
BitmapHeader.Width = ImageWidth;
BitmapHeader.Height = ImageHeight;
BitmapHeader.NumberOfPlanes = 1;
BitmapHeader.NumberOfBitsPerPixel = 24;
BitmapHeader.CompressionType = BI_RGB;
BitmapHeader.ImageSize = (NumberOfDoubleWordsPerImageRow << 2) * ImageHeight;
BitmapHeader.NumberOfHorizontalPixelsPerMeter = 0;
BitmapHeader.NumberOfVerticalPixelsPerMeter = 0;
BitmapHeader.NumberOfUsedPaletteColors = 0;
BitmapHeader.NumberOfImportantPaletteColors = 0;
WindowDeviceContextHandle = GetDC(WindowHandle);
BitmapHandle = CreateDIBSection(WindowDeviceContextHandle, &BitmapHeader, DIB_RGB_COLORS, (void**)(&ImageData), NULL, 0);
if (BitmapHandle != NULL)
{
DeviceContextHandle = CreateCompatibleDC(WindowDeviceContextHandle);
if (DeviceContextHandle == NULL)
{
DeleteObject(BitmapHandle);
}
else
{
SelectObject(DeviceContextHandle, BitmapHandle);
}
}
Code:
void SetPixel(int x, int y, unsigned int Color)
{
int XDividedBy4;
int Index;
// Note: Point (0, 0) is at the upper left corner of the image.
if ((x >= 0) && (x < ImageWidth) && (y >= 0) && (y < ImageHeight))
{
Color = Color & 0x00FFFFFF;
XDividedBy4 = x >> 2;
Index = ((ImageHeight - 1 - y) * NumberOfDoubleWordsPerImageRow) + XDividedBy4 + XDividedBy4 + XDividedBy4;
switch (x & 3)
{
case 0:
ImageData[Index] = (ImageData[Index] & 0xFF000000) | Color;
break;
case 1:
ImageData[Index] = (ImageData[Index] & 0x00FFFFFF) | (Color << 24);
ImageData[Index + 1] = (ImageData[Index + 1] & 0xFFFF0000) | (Color >> 8);
break;
case 2:
ImageData[Index + 1] = (ImageData[Index + 1] & 0x0000FFFF) | (Color << 16);
ImageData[Index + 2] = (ImageData[Index + 2] & 0xFFFFFF00) | (Color >> 16);
break;
case 3:
ImageData[Index + 2] = (ImageData[Index + 2] & 0x000000FF) | (Color << 8);
break;
}
}
}
BitBlt() copies the image data from the main memory to the graphic card's memory. This should be done when the window is repainted.
Code:
case WM_PAINT:
WindowDeviceContextHandle = GetDC(WindowHandle);
BeginPaint(WindowHandle, &Paint);
BitBlt(Paint.DeviceContextHandle,
Paint.Rectangle.Left, Paint.Rectangle.Top,
Paint.Rectangle.Right - Paint.Rectangle.Left,
Paint.Rectangle.Bottom - Paint.Rectangle.Top,
WindowDeviceContextHandle, Paint.Rectangle.Left, Paint.Rectangle.Top, SRCCOPY);
EndPaint(WindowHandle, &Paint);
I hope this clears up some of your misery.
Coder Dave
-
Re: Draw Image Using 2D Byte Array ?
Thank you so much Mr.Dave.
Reading this code little difficult to understand. B'cos I'm fresher.
Its OK I will study & try to use this code. If any doubt, I come back with you.
If this code helps to reach my goal, really I'm very happy.
One Again Thank you Mr.Dave.
-
1 Attachment(s)
Re: Draw Image Using 2D Byte Array ?
hi,
I tried the code and also felt little difficult. Here by I attached the code.
I want to display : Bit Count = 8 + Monochrome image display.
Code for Bit-count = 32 :
*****************************
Code:
void CFrame::OnPaint()
{
// Byte Array Display
CDC* pDC=GetDC();
HDC hDC = *pDC;
HDC hDCMem = CreateCompatibleDC(hDC);
BYTE* ImgData;
BITMAPINFO bi;
ZeroMemory(&bi, sizeof(BITMAPINFO));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth =512;
bi.bmiHeader.biHeight = -256; //negative so (0,0) is at top left
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
HBITMAP bitmap = ::CreateDIBSection(hDCMem, &bi, DIB_RGB_COLORS, (VOID**)&ImgData, NULL, 0);
HGDIOBJ oldbmp = ::SelectObject(hDCMem, bitmap);
FILE *fpCsv;
if( ( fpCsv = fopen ("Blitting.txt","w")) == NULL )
{
MessageBox("Failed to Write Blitting.txt!","Warning",MB_OK);
return;
}
int pitch = 4*512; // 4 bytes per pixel but if not 32 bit, round pitch up to multiple of 4
int index;
for(int x=0; x<512; x=x++)
{
for(int y=0; y<256; y++)
{
index = y * pitch;
index += x*4;
ImgData[index + 0] = y; // 0 ,1 ,... ,255
ImgData[index + 1] = y;
ImgData[index + 2] = y;
fprintf(fpCsv, "%d, %d, %d \n ", index, index+1, index+2);
}
fprintf(fpCsv, "Count = %d\n\n", x);
}
fclose(fpCsv);
BitBlt(hDC, 0, 0, 512, 256, hDCMem, 0, 0, SRCCOPY);
//SelectObject(hDCMem,oldbmp);
DeleteDC(hDCMem);
DeleteObject(bitmap);
//Invalidate(false);
}
I have one more doubt, Index are calculated using by pitch, x & y variables & also storing the data like
Line 1 : 0,512,1024,... //Index value
Line 2 : 1,513,1025....
.
.
Line 512 : 2,514,2048....
why will we store the data in this format?
Pls find the attachment. Am I going in the right path?
-
Re: Draw Image Using 2D Byte Array ?
First I would like to point out that there was an error in my code above that handles the WM_PAINT message. It should have read
Code:
case WM_PAINT:
BeginPaint(WindowHandle, &Paint);
BitBlt(Paint.DeviceContextHandle,
Paint.Rectangle.Left, Paint.Rectangle.Top,
Paint.Rectangle.Right - Paint.Rectangle.Left,
Paint.Rectangle.Bottom - Paint.Rectangle.Top,
DeviceContextHandle, Paint.Rectangle.Left, Paint.Rectangle.Top, SRCCOPY);
EndPaint(WindowHandle, &Paint);
where DeviceContextHandle is the device context handle returned by the call to CreateCompatibleDC(). I am using the BeginPaint() and EndPaint() functions so that the entire bitmap does not have to be copied for each paint event. Only the portion of the bitmap needed to redraw the client area is copied. Note that I am not using MFC, so the window handle has to be explicitly passed to the GetDC(), BeginPaint(), and EndPaint() Windows API functions. SaraswathiSrinath, you are passing the correct source device context handle in your call to BitBlt(), so maybe you caught my error.
Now about your code ... You should be creating the bitmap object and compatible device context in the window's create event, not in the paint event. You only want to create the bitmap object once. The paint event happens every time the window's client area needs to be redrawn, such as when another window is moved over the top of it. The code to fill the bitmap should be elsewhere as well. In your example, it should probably be in the window's create event after the bitmap object is created. The bitmap handle, the compatible device context handle, and the pointer to the image data will need to be stored in static variables so that their values are retained between events. The compatible device context and the bitmap object should be deleted in the window's destroy event. The image data memory will automatically be released when the bitmap object is deleted. Also, writing files from the paint event is a bad idea since the paint event occurs many, many times.
I have always used displays with 24-bit color. I do not understand why you are using 32 bits per pixel. 8-bit color requires a color palette, but that is probably not the route you want to take for modern graphic cards. Your code assigns the same value to the red, green, and blue components of the pixels, which is the right way to get gray.
The image data is stored as a series of horizontal rows. Each row contains 3 bytes per pixel, plus up to 3 unused bytes in order to make the number of bytes in a row a multiple of 4. Your variable pitch would be the number of bytes it takes to store one row of the bitmap, though you are using 32 bits per pixel instead of 24. The first byte of each pixel is the blue component. The second byte is the green component. The third byte is the red component. If you were to look inside a bitmap image file, the image data would appear exactly as it does in the image data array.
-
Re: Draw Image Using 2D Byte Array ?
Hi Mr.Dave,
Yes. First I was create the bitmap object and compatible device context in the window's create event,
But didn't worked, so that I wrote the code in paint event. May be My code contain anything wrong.
This is first time I'm handling Bitmap with real-time data.
My requirement is, I get the [1024][256] data at every sec.
Using this data I make the bitmap in grayscale with fast display. But I'm sure , I'm getting 8bits per pixels.
So that only I used the Bit-count = 8; Is it correct? For this requirement, can I use the 24-bit color displays?
I changed my code like below for bit-count = 8 :
Code:
bi.bmiHeader.biBitCount = 8;
int pitch = 1*512;
index += x*1;
ImgData[index + 0] = y;
But I don't know is this correct?
Thanks for your reply. I will correct my code and come back.
For you experience, you have any sample code means, Pls post me for understand the concept.
-
Re: Draw Image Using 2D Byte Array ?
The bitmap object handle and the compatible device context handle need to be stored such that their values are retained after the window's create event is done. I have never used MFC, but apparently it splits the window's events into separate functions. This prohibits the use of local static variables to store information needed by multiple events. Perhaps, you could make the bitmap object handle and compatible device context handle into class variables. As a very last resort, you could make them global variables.
I played around with creating a color palette for a bitmap that uses 8 bits per pixel. The following code listing is a complete test application. I am not using MFC.
Code:
#include <windows.h>
LRESULT CALLBACK ProcessWindowEvent(HWND WindowHandle, UINT MessageCode, WPARAM WParameter, LPARAM LParameter)
{
static int ClientWidth = 0;
static int ClientHeight = 0;
static int NumberOfBytesPerRow = 0;
static HBITMAP BitmapObjectHandle = NULL;
static BYTE* ImageData = NULL;
static HDC CompatibleDeviceContextHandle = NULL;
struct MyBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
};
LRESULT ReturnValue;
RECT ClientRectangle;
MyBITMAPINFO Bitmap;
int Index;
HDC WindowDeviceContextHandle;
int y;
int x;
PAINTSTRUCT Paint;
ReturnValue = 0;
switch (MessageCode)
{
case WM_CREATE:
GetClientRect(WindowHandle, &ClientRectangle);
ClientWidth = ClientRectangle.right - ClientRectangle.left;
ClientHeight = ClientRectangle.bottom - ClientRectangle.top;
NumberOfBytesPerRow = (ClientWidth + 3) & 0xFFFFFFFC;
Bitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Bitmap.bmiHeader.biWidth = ClientWidth;
Bitmap.bmiHeader.biHeight = -ClientHeight;
Bitmap.bmiHeader.biPlanes = 1;
Bitmap.bmiHeader.biBitCount = 8;
Bitmap.bmiHeader.biCompression = BI_RGB;
Bitmap.bmiHeader.biSizeImage = NumberOfBytesPerRow * ClientHeight;
Bitmap.bmiHeader.biXPelsPerMeter = 0;
Bitmap.bmiHeader.biYPelsPerMeter = 0;
Bitmap.bmiHeader.biClrUsed = 256;
Bitmap.bmiHeader.biClrImportant = 256;
for (Index = 0; Index < 256; Index = Index + 1)
{
Bitmap.bmiColors[Index].rgbBlue = Index;
Bitmap.bmiColors[Index].rgbGreen = Index;
Bitmap.bmiColors[Index].rgbRed = Index;
Bitmap.bmiColors[Index].rgbReserved = 0;
}
WindowDeviceContextHandle = GetDC(WindowHandle);
BitmapObjectHandle = CreateDIBSection(WindowDeviceContextHandle, (BITMAPINFO*)(&Bitmap), DIB_RGB_COLORS, (void**)(&ImageData), NULL, 0);
if (BitmapObjectHandle != NULL)
{
CompatibleDeviceContextHandle = CreateCompatibleDC(WindowDeviceContextHandle);
if (CompatibleDeviceContextHandle != NULL)
{
SelectObject(CompatibleDeviceContextHandle, BitmapObjectHandle);
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;
}
}
}
}
break;
case WM_DESTROY:
if (CompatibleDeviceContextHandle != NULL)
{
DeleteDC(CompatibleDeviceContextHandle);
}
if (BitmapObjectHandle != NULL)
{
DeleteObject(BitmapObjectHandle);
}
PostQuitMessage(0);
break;
case WM_ERASEBKGND:
break;
case WM_PAINT:
if (CompatibleDeviceContextHandle != NULL)
{
BeginPaint(WindowHandle, &Paint);
BitBlt(Paint.hdc, Paint.rcPaint.left, Paint.rcPaint.top,
Paint.rcPaint.right - Paint.rcPaint.left, Paint.rcPaint.bottom - Paint.rcPaint.top,
CompatibleDeviceContextHandle, Paint.rcPaint.left, Paint.rcPaint.top, SRCCOPY);
EndPaint(WindowHandle, &Paint);
}
break;
default:
ReturnValue = DefWindowProc(WindowHandle, MessageCode, WParameter, LParameter);
}
return ReturnValue;
}
int APIENTRY WinMain(HINSTANCE InstanceHandle, HINSTANCE PreviousInstanceHandle, char* CommandLine, int CommandShow)
{
int ReturnValue;
WNDCLASS Window;
char* ClassName = "Test";
short int WindowClassAtom;
RECT WindowRectangle;
HWND WindowHandle;
int WindowMessageWasFound;
MSG WindowMessage;
ReturnValue = 0;
Window.style = CS_OWNDC;
Window.lpfnWndProc = &ProcessWindowEvent;
Window.cbClsExtra = 0;
Window.cbWndExtra = 0;
Window.hInstance = InstanceHandle;
Window.hIcon = NULL;
Window.hCursor= LoadCursor(NULL, IDC_ARROW);
Window.hbrBackground= HBRUSH(GetStockObject(NULL_BRUSH));
Window.lpszMenuName = NULL;
Window.lpszClassName = ClassName;
WindowClassAtom = RegisterClass(&Window);
if (WindowClassAtom != 0)
{
WindowRectangle.left = 0;
WindowRectangle.right = 512;
WindowRectangle.top = 0;
WindowRectangle.bottom = 256;
AdjustWindowRect(&WindowRectangle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, false);
WindowHandle = CreateWindow(ClassName, "Test App",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, WindowRectangle.right - WindowRectangle.left,
WindowRectangle.bottom - WindowRectangle.top, NULL, NULL, InstanceHandle, NULL);
if (WindowHandle != NULL)
{
ShowWindow(WindowHandle, CommandShow);
UpdateWindow(WindowHandle);
WindowMessageWasFound = GetMessage(&WindowMessage, NULL, 0, 0);
while (WindowMessageWasFound)
{
TranslateMessage(&WindowMessage);
DispatchMessage(&WindowMessage);
ReturnValue = WindowMessage.wParam;
WindowMessageWasFound = GetMessage(&WindowMessage, NULL, 0, 0);
}
}
UnregisterClass(ClassName, InstanceHandle);
}
return ReturnValue;
}
-
Re: Draw Image Using 2D Byte Array ?
Thank you for your reply.
But I know only MFC :)
As you said I create the CreateCompatibleDC(hDC) in the Constructor instead of OnPaint() Method.
But if any other window appear under the application, Its not working.
I will read your code & Try my level best.
-
1 Attachment(s)
Re: Draw Image Using 2D Byte Array ?
Hi Mr.Dave,
I Done the concept using your code. Really Very Happy.
Please find the attachment & run it.
I have one more doubt.
In that code I will replace the real time data like below in OnPaint() method, Am I going in the correct path?
Code:
for (y = 0; y < ClientHeight; y = y + 1)
{
Index = y * NumberOfBytesPerRow;
for (x = 0; x < ClientWidth; x = x + 1)
{
ImageData[Index] = RealtimeData[y];
Index = Index + 1;
}
}
I like to paint the Real time data continuously. How Can I run the OnPaint method continuously?
I'm using Dialog Based Application.
For continuous real time data display, I used Invalidate(false); [OR] UpdateData(true); method means,Buttons are hidden at run time and also hidden if any other window maximize and minimize case.
Waiting for your valuable reply :)
-
Re: Draw Image Using 2D Byte Array ?
Since Windows is event driven, there needs to be an event that occurs periodically in order for the display to be updated with new data. This event could be a timer event. You start a timer by calling SetTimer(), perhaps in the create event code, and stop the timer by calling KillTimer(), perhaps in the destroy event code. It is within the code that handles the timer event that you want to sample the incoming data and redraw the image accordingly. After the image has been redrawn, call InvalidateRect(). This will put a paint message on the window's event queue. The code in the paint event then calls BitBlt() to update the display. To repaint the display immediately, call UpdateWindow() after the call to InvalidateRect(). Make sure to use BeginPaint() and EndPaint() in the code for the paint event. Otherwise, the paint event will be invoked endlessly.
Code:
case WM_PAINT:
// The image should not be redrawn in the paint event.
// The display just gets updated with the current image.
BeginPaint(WindowHandle, &Paint);
BitBlt(Paint.hdc, Paint.rcPaint.left, Paint.rcPaint.top,
Paint.rcPaint.right - Paint.rcPaint.left, Paint.rcPaint.bottom - Paint.rcPaint.top,
CompatibleDeviceContextHandle, Paint.rcPaint.left, Paint.rcPaint.top, SRCCOPY);
EndPaint(WindowHandle, &Paint);
break;
case WM_TIMER:
// < code to sample the incoming data and redraw the image >
// Update the entire client area.
InvalidateRect(WindowHandle, NULL, false);
UpdateWindow(WindowHandle);
break;
-
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.
-
Re: Draw Image Using 2D Byte Array ?
Thanks Mr.Dave.
I will try & come back.