Cannot draw polygons using XCB in C - c

Just started with XCB programming with C. I have written this code which will create a window and draw some points and a rectangle:
#include <stdlib.h>
#include <stdio.h>
#include <xcb/xcb.h>
int main() {
xcb_connection_t *connection = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(connection)) {
printf("Error setting up connection to X\n");
exit(1);
}
const xcb_setup_t *setup = xcb_get_setup(connection);
xcb_screen_t *screen = xcb_setup_roots_iterator(setup).data;
// Create wndow
xcb_window_t window_id = xcb_generate_id(connection);
uint32_t prop_name = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t prop_value[2];
prop_value[0] = screen->white_pixel;
prop_value[1] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_EXPOSURE;
xcb_create_window(connection, screen->root_depth, window_id, screen->root, 100, 100, 500, 400, 1,
XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, prop_name, &prop_value);
xcb_map_window(connection, window_id);
xcb_flush(connection);
uint32_t gc_value_mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
uint32_t gc_value_list[2];
gc_value_list[0] = screen->black_pixel;
gc_value_list[1] = 0;
xcb_drawable_t drawable_window = screen->root;
xcb_gcontext_t context_id = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_gc(connection, context_id, drawable_window, gc_value_mask, gc_value_list);
// Create polygons
xcb_point_t points[5] = {{10, 10}, {10, 50}, {40, 70}, {70, 40}, {50, 10}};
xcb_rectangle_t rect = {50, 50, 100, 50};
// Main loop
xcb_generic_event_t *event;
while ((event = xcb_wait_for_event(connection))) {
switch (event->response_type) {
case XCB_KEY_PRESS:
break;
case XCB_BUTTON_PRESS:
break;
case XCB_EXPOSE:
printf("Expose event called\n");
// Draw polygons
xcb_poly_point(connection, XCB_COORD_MODE_ORIGIN, drawable_window, context_id, 4, points);
xcb_poly_fill_rectangle(connection, drawable_window, context_id, 1, &rect);
xcb_flush(connection);
default:
break;
}
free(event);
}
return 0;
}
It has compiled properly and there was no warning or error at runtime. But, I just get a window with no graphics. What am I doing wrong?

I think your xcb_poly_fill_rectangle(), etc., are trying to draw on the root window. At least, you're passing screen->root as the drawable argument. It works for me if I pass window_id here.
I'm really not sure why XCB needs all these various context arguments, and the exact functions of each do not seem to be well-documented.

Kevin Boone is correct: You are drawing to the root window.
I did the following change to your program (it is the same one that Kevin suggested):
--- t.c.orig 2020-09-18 15:06:38.344441255 +0200
+++ t.c 2020-09-18 15:06:48.104167556 +0200
## -26,7 +26,7 ## int main() {
uint32_t gc_value_list[2];
gc_value_list[0] = screen->black_pixel;
gc_value_list[1] = 0;
- xcb_drawable_t drawable_window = screen->root;
+ xcb_drawable_t drawable_window = window_id;
xcb_gcontext_t context_id = xcb_generate_id(connection);
xcb_void_cookie_t cookie = xcb_create_gc(connection, context_id, drawable_window, gc_value_mask, gc_value_list);
This results in the following window contents being shown. You can see both the rectangle and the individual pixels being shown:
Please do not accept this answer, but instead Kevin Boone's. I only wanted to add the screenshot.

Related

Xlib image grab fails in XGetImage

Cookie cuttered (from supposedly working code) a trivial C program to perform a Xlib image grab using XGetImage(). At this point I'm not trying to process the image, this is just a proof-of-concept to see if the image grab works - and it doesn't. The XGetImage() call fails like:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 73 (X_GetImage)
Serial number of failed request: 21
Current serial number in output stream: 21
I spent a fair amount of time researching this and apparently this problem has plagued other developers and no definitive answer was ever arrived at. Does someone know how I could go about resolving this? I can tell from the printf that the window of interest was correctly identified. The XMapRaised() is a suggestion from a prior thread on this problem, but doesn't seem to help. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "/usr/include/X11/Xlib.h"
Window findScidWindow(Display *display )
{
Bool found = False;
Window rootWindow = RootWindow(display, DefaultScreen(display));
Atom atom = XInternAtom(display, "_NET_CLIENT_LIST", True);
Atom actualType;
int format;
unsigned long numItems;
unsigned long bytesAfter;
unsigned char *data = '\0';
Window *list;
char *windowName;
int status = XGetWindowProperty(display, rootWindow, atom, 0L, (~0L), False,
AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, &data);
list = (Window *)data;
if (status >= Success && numItems)
{
for (int i = 0; i < numItems; ++i)
{
status = XFetchName(display, list[i], &windowName);
if (status >= Success)
{
if(strstr(windowName, "Scid vs. PC") != NULL)
{
XFree(windowName);
XFree(data);
return list[i];
}
}
}
}
}
void
main( int argc, char*argv )
{
Display* d = XOpenDisplay(":0.0");
XImage *image;
Window root = (Window)0x0560003b; /* obtained via 'wmctrl -l -G' */
Window ScidWindow = findScidWindow(d);
XWindowAttributes attrib;
XGetWindowAttributes(d, ScidWindow, &attrib);
int width = attrib.width;
int height = attrib.height;
printf("width: %d height: %d\n",width,height);
XMapRaised(d, root);
/* coordinates 438,110 obtained via 'wmctrl -l -G' */
image = XGetImage( d, ScidWindow, 438, 110, width, height, AllPlanes, ZPixmap);
}
The issue is
image = XGetImage( d, ScidWindow, 438, 110, width, height, AllPlanes, ZPixmap);
uses x = 438 and y = 110 that is particular a problem if x + width is actually bigger as the window width (same for the height)
So here I have to assume you're not attempting to crop the window image but rather want to take a plain raw screenshot, then you just need to pass 0 for x and y:
image = XGetImage( d, ScidWindow, 0, 0, width, height, AllPlanes, ZPixmap);
The explanation is that the coordination system is not the full display or screen but the one of the window you are grabbing. Means the window starts at (0, 0).
This took me also some time to figure out.

Sending pointer to a struct through a queue in FreeRTOS

I can't seem to figure out how to send a pointer to a struct using a queue in FreeRTOS. I've tried all I could think of, yet I always get a pointer to some random region of memory.
I'm trying to send a pointer to a button struct to another task, where it will then be drawn on the screen. I tried sending the whole object and it worked, but since there's a lot of data in the struct (data of two icons) I don't really want to do that.
The code is being run in Atmel SAME70 Xplained.
Here is a simpler version of the code I'm working on:
typedef struct {
uint32_t width;
uint32_t height;
uint32_t x;
uint32_t y;
uint8_t status;
void (*callback)(t_but);
tImage iconOn;
tImage iconOff;
} t_but;
void task_lcd(void) {
xQueueButtons = xQueueCreate(6, sizeof(struct t_but *));
t_but *button;
configure_lcd();
draw_screen();
while (1) {
if (xQueueReceive(xQueueButtons, &(button), (TickType_t)500 / portTICK_PERIOD_MS)) {
// This always prints some random numbers.
printf("Button X: %" PRIu32 "\r\n", button->x);
}
}
}
void task_buttons(void) {
t_but butPlay = {.width = 64,
.height = 64,
.x = 60,
.y = 445,
.status = 0,
.callback = &ButPlayCallback,
.iconOn = play_red,
.iconOff = play_black};
xQueueSend(xQueueButtons, &butPlay, 0);
while (1) {
// Some other code.
}
}
Any help is very much appreciated.
It appears from the API that the xQueueSend does a copy via the pointer passed so if you want to pass a pointer on the queue you need to pass the address of a pointer that is pointing at your structure.
void task_buttons(void) {
t_but butPlay = {.width = 64,
.height = 64,
.x = 60,
.y = 445,
.status = 0,
.callback = &ButPlayCallback,
.iconOn = play_red,
.iconOff = play_black};
t_but * const p_but = &butPlay;
xQueueSend(xQueueButtons, &p_but, 0);
while (1) {
// Some other code.
}
}

IMG_Load: Couldn't open xxx.png

Context: I am currently trying to practice my C skills a little bit with the SDL 2.0.7 and SDL2_image-2.0.2.
Problem: I get an error message during the execution of my program "IMG_Load: Couldn't open xxx.png". The error seems stupid as it is very explicit: "i can't find the image", but as the image is in the appropriate folder... I think I need a fresh eye to spot the stupid mistake.
Platform: Windows 10
IDE: Visual Studio 2017
Steps done to solve the problem:
1) Tried to reduce my code lenght/functionalities to its minimum. Result: Error is still here.
2) I created a new project and copy/pasted the simplified code. Result: On the new project, there is no error, everything is working fine.
3) I compared project's options and the folder. To me they are the same:
It shouldn't be useful but just in case, here is my:
Code sample:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_render.h>
#include "SDL_timer.h"
int main(int argc, char *argv[])
{
printf("argc = %d\n", argc);
for (int i = 0; i < argc; ++i)
{
printf("argv[ %d ] = %s\n", i, argv[i]);
}
SDL_Window* pWindow = NULL;
SDL_Renderer* pRenderer = NULL;
SDL_Texture* pTexture = NULL;
SDL_Surface* pLoadedSurface = NULL;
SDL_Rect* tileClipsArray = NULL;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
{
fprintf(stderr, "Erreur d'initialisation de la SDL : %s\n", SDL_GetError());
}
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf("IMG_Load: %s\n", IMG_GetError());
}
pWindow = SDL_CreateWindow("TestLoadingImage",
SDL_WINDOWPOS_CENTERED, // initial X position.
SDL_WINDOWPOS_CENTERED, // Initial Y position.
640, // Width, in pixels.
480, // Height, in pixels.
SDL_WINDOW_OPENGL); // Window flags
assert(NULL != pWindow);
//Create renderer for the window
pRenderer = SDL_CreateRenderer(pWindow,
-1, // Index of the rendering driver to initialize, -1 to initialize the first one supporting the requested flags.
SDL_RENDERER_ACCELERATED
| SDL_RENDERER_PRESENTVSYNC); // RendererFlags
assert(NULL != pRenderer);
//Initialize renderer color
SDL_SetRenderDrawColor(pRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
pLoadedSurface = IMG_Load("GroundTiles.png");
if (NULL == pLoadedSurface)
{
printf("IMG_Load: %s\n", IMG_GetError());
assert(NULL != pLoadedSurface);
}
//Create texture from surface pixels
pTexture = SDL_CreateTextureFromSurface(pRenderer, pLoadedSurface);
assert(NULL != pTexture);
//Get image dimensions
const int textureWidth = pLoadedSurface->w;
const int textureHeight = pLoadedSurface->h;
const int tileClipWidth = 128;
const int tileClipHeight = 128;
const int nbLines = textureHeight / tileClipHeight;
const int nbColumns = textureWidth / tileClipWidth;
const int nbTileClips = nbLines + nbColumns;
tileClipsArray = malloc(nbTileClips * sizeof(SDL_Rect));
int tileClipIndex = 0;
for (int tileClipLineIndex = 0; tileClipLineIndex < nbLines; ++tileClipLineIndex)
{
for (int tileClipColumnIndex = 0; tileClipColumnIndex < nbColumns; ++tileClipColumnIndex)
{
tileClipsArray[tileClipIndex].x = tileClipColumnIndex * tileClipWidth;
tileClipsArray[tileClipIndex].y = tileClipLineIndex * tileClipHeight;
tileClipsArray[tileClipIndex].w = tileClipWidth;
tileClipsArray[tileClipIndex].h = tileClipHeight;
++tileClipIndex;
}
}
//Get rid of old loaded surface
SDL_FreeSurface(pLoadedSurface);
pLoadedSurface = NULL;
int canLoop = 1;
SDL_Event event;
int lastUpdate = SDL_GetTicks();
int now = 0;
int timeToSpendPerClip = 5000;
int timeSpentwithThisClip = 0;
int clipToUse = 0;
while (canLoop)
{
now = SDL_GetTicks();
if (now - lastUpdate > 16)
{
timeSpentwithThisClip += now - lastUpdate;
lastUpdate = now;
// We are processing all the events received this frame.
while (SDL_PollEvent(&event))
{
// We need to know what kind of event we are dealing with.
switch (event.type)
{
case SDL_QUIT:
canLoop = 0;
break;
}
}
SDL_RenderClear(pRenderer);
if (timeSpentwithThisClip > timeToSpendPerClip)
{
clipToUse = rand() % 4;
timeSpentwithThisClip = 0;
}
// Set rendering space and render to screen.
SDL_Rect renderQuad;
renderQuad.x = 50;
renderQuad.y = 50;
renderQuad.w = tileClipsArray[clipToUse].w;
renderQuad.h = tileClipsArray[clipToUse].h;
SDL_RenderCopyEx(pRenderer, pTexture, &tileClipsArray[clipToUse], &renderQuad, 0.0, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(pRenderer);
}
}
SDL_DestroyTexture(pTexture);
free(tileClipsArray);
SDL_DestroyRenderer(pRenderer);
pRenderer = NULL;
SDL_DestroyWindow(pWindow);
pWindow = NULL;
IMG_Quit();
SDL_Quit();
return EXIT_SUCCESS;
}
I'm probably going to copy/paste all my files from the project 1 into the project 2, but I would like to understand my mistake!

How can i add line breaks when rendering Text using X11,

I am making an application that renders texts according to style mentioned on screen using X Windows System and Xft. My code is working fine as shown below.
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
char * nowShowing()
{
return strdup("This is a sample text This is rendered with new Driver installed This is a sample text his is rendered with new Driver installed");
}
int main()
{
XftFont *font;
XftDraw *draw;
XRenderColor render_color;
XftColor xft_color;
char *str;
str = nowShowing();
int x = 70;
int y = 150;
Display *dis = XOpenDisplay (0);
int screen = DefaultScreen (dis);
Window w = XCreateSimpleWindow (dis, RootWindow (dis, screen),
0, 0, 1200, 300, 1,
BlackPixel (dis, screen),
WhitePixel (dis, screen));
XEvent ev;
render_color.red = 0;
render_color.green =0;
render_color.blue = 0;
render_color.alpha = 0xffff;
XftColorAllocValue (dis,
DefaultVisual(dis, screen),
DefaultColormap(dis, screen),
&render_color,
&xft_color);
//font = XftFontOpen(dis, screen,
// XFT_FAMILY, XftTypeString, "charter",
// XFT_SIZE, XftTypeDouble, 20.0,
// NULL);
font = XftFontOpenName(dis,screen,"URW Palladio L:style=Bold Italic"); //it takes a Fontconfig pattern string
draw = XftDrawCreate(dis, w,
DefaultVisual(dis, screen),
DefaultColormap(dis, screen));
XSelectInput (dis, w, ExposureMask);
XMapWindow (dis, w);
for (;;)
{
XNextEvent (dis, &ev);
if (ev.type == Expose)
XftDrawString8(draw, &xft_color, font, x, y, (XftChar8 *) str,
strlen(str));
}
return 0;
}
But i am wondering that how can i add line breaks in the text entered. I tried using "/n" and also tried to make array and used loops but it didn't work.
New line "\n" will not be rendered by Xft. You need to render each line separately with proper offset, depending on font size and desired spacing.
I have modified the ending block of your code with sample text rendered two times on separate lines.
if (ev.type == Expose)
{
int fonth = font->ascent + font->descent;
XftDrawString8(draw, &xft_color, font, x, y, (XftChar8 *) str,
strlen(str));
XftDrawString8(draw, &xft_color, font, x, y+fonth, (XftChar8 *) str,
strlen(str));
}

Performance issue while using PictureBox

I'm working on an application in Visual Studio 2010 and I'm coding in C++/CLI.
In my previous questions I had issue with data series from a serial port. Now it seems ok and now I'm trying to plot them.
I don't want to use Chart, so I would like to use handmade functions that use the class Graphics. In order to test my code, I created two arrays: the first one is filled with values coming from a Gaussian. The second one is filled with random numbers.
When I plot the values, I would like to see my plot growing and updating just like an oscilloscope. The second Do_Plot manages to "remove point" plotting them by the BackColor.
All the code works as intended but I'm experiencing problem with performances. If I run the code on my Pc, my series is plotted every 500/700 ms.
Sometimes it slows down to 1500ms and then it comes back faster.
I tried to run the code on my coworkers' Pc and I noticed the series is plotted every 170ms on the first one, whereas the series is plotted every 950ms on the second one.
This is the code:
System::Void Form1::button1_Click(System::Object^ sender, System::EventArgs^ e) {
button1->Enabled = false;
array<float,1>^ Gauss = gcnew array<float,1>(1001);
array<float,1>^ Rumore = gcnew array<float,1>(1001);
/*Some useful variables*/
Random^ generatore = gcnew Random;
float a = safe_cast<float>(Math::Round(5/(SIGMA*Math::Sqrt(2*PI)), 2));
float b = safe_cast<float>(2*(SIGMA*SIGMA));
/*Start */
float portante;
float r;
float s;
int convX =1000/1000;
int convY =500/2;
/*time variables */
int bias = 50;
int dif =600;
/*Gap between drawing and removing*/
int k = 3;
int e1 = 0;
for ( ; ; ) {
/*Start*/
clock_t Start = clock();
if(textBox1->Text==""){
portn = 5;
}
else
portn = float::Parse(textBox1->Text);
/*temp variables to go out the for cycle */
portante = portn;
r = rand;
s = sig;
/ckeck state is OK */
check = 0;
for(int i = 1; i<=1000; i++) {
Gauss[i] = safe_cast<float>(Math::Round( a*s*Math::Exp(-Math::Pow(((0.01*1*(i))-portante), 2)/b), 2));
Rumore[i] = safe_cast<float>(Math::Round(r*generatore->NextDouble(), 2));
bool clipSup = ClipSup(2, Gauss[i]+Rumore[i]);
if(clipSup==true) {
Gauss[i] = 1.99f;
Rumore[i] = 0;
}
Do_Plot(g, disegna, i-1, Gauss[i-1]+Rumore[i-1], i, Gauss[i]+Rumore[i], convX, convY);
e1 =(k+i)%1000;
Do_Plot(g, rimuovi, e1, Gauss[e1]+Rumore[e1], e1+1, Gauss[e1+1]+Rumore[e1+1], convX, convY);
/*Ckeck if go out for cycle*/
if(check == CODE_1 ) {
portante = portn;
break;
}
if(check == CODE_2 ) {
r = rand;
break;
}
if(check == CODE_3 ) {
s = sig;
break;
}
}
clock_t Stop = clock();
int Diff = Stop-Start;
label8->Text = Convert::ToString(Diff);
int tempDiff = (Stop-Start)+bias;
if(tempDiff>dif)
{
//Do_Axes(g); /*Do Axes*/
//Do_Grid(g); /*Do Grid */
Application::DoEvents();
dif = 600;
bias = 0;
}
else
bias +=50; //Else bias grows
}
}
Where Do_Plot is:
void Do_Plot(Graphics^ g, Pen^ penna, int Xi, float Yi, int Xf, float Yf, int convX, int convY) {
g->DrawLine(penna, (convX*Xi+50), safe_cast<int>(500-(Yi*convY)+50),
(convX*Xf+50), safe_cast<int>(500-(Yf*convY)+50));
}
I have declared Graphics^ g here:
public ref class Form1 : public System::Windows::Forms::Form
{
Graphics^ g;
public:
Form1(void)
{
InitializeComponent();
//
//TODO: aggiungere qui il codice del costruttore.
//
g = pictureBox1->CreateGraphics();
}
Onestly I don't know why my code works so differently when it runs on another Pc. I think the problem is g = pictureBox1->CreateGraphics(); but I'm just doing some hypothesis. Any kind of help would be really appreciated cause I'm stuck on this one since the previous week!!
Thanks a lot!
Emiliano
I am going to give you the code in c/c++. Will then find how to do it in c++/cli
First initialize the objects we will use (begining of button_click):
RECT rt = {0, 0, 1200, 600};
HBITMAP hBitmap = NULL;
HPEN hLinePen = NULL;
HDC hdcPctrBox = NULL, hdc = NULL, hdcMemTempImage = NULL;
HBRUSH hBrush = NULL;
POINT arrayPnt[1000]; //array of points
hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
hdcPctrBox = GetWindowDC(hwndPctrBox); //hwndPctrBox is the handle of picturebox
hdcMemTempImage = CreateCompatibleDC(hdc);
hBitmap = CreateCompatibleBitmap(hdc, 1200, 600);
SelectObject(hdcMemTempImage, hBitmap);
hLinePen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); //width of pen = 1,and color (255, 0, 0)
SelectObject(hdcMemTempImage, hLinePen);
hBrush = CreateSolidBrush(RGB(100, 100, 255)); //color of picturebox
Then:
for ( ; ; ) {
/*Start*/
clock_t Start = clock();
FillRect(hdcMemTempImage, &rt, hBrush); //clear the hdcMemTempImage with the picturebox color
//your code continues...
In the for(int i = 1; i<=1000; i++) add one point at a time:
arrayPnt[i - 1].x = X; //calculate X
arrayPnt[i - 1].x = Y; ////calculate Y
And finaly we draw it, after the for loop and before the clock_t Stop (we dont need the Do_Plot()):
Polyline(hdcMemTempImage, &arrayPnt, 1000);
BitBlt(hdcPctrBox, 0, 0, 1200, 600, hdcMemTempImage, 0, 0, SRCCOPY);
clock_t Stop = clock();
//your code continues...
EDIT: use your original code(you dont need rt, hBitmap, hBrush, hdcMemTempImage, arrayPnt and hdc) and instead of calling Do_Plot() add this code:
//create two pens, one with the color you want hLinePen, and another with the color of picturebox hLinePenErase
//inside for(int i = 1; i<=1000; i++)
(some code...)
if(clipSup==true) {
Gauss[i] = 1.99f;
Rumore[i] = 0;
}
SelectObject(hdcPctrBox, hLinePen); //the pen to draw the line
MoveToEx(hdcPctrBox, xStart, yStart, NULL); //start point of line
LineTo(hdcPctrBox, xEnd, yEnd); //end point of line
SelectObject(hdcPctrBox, hLinePenErase); //the pen to erase the line
MoveToEx(hdcPctrBox, xStartErase, yStartErase, NULL); //start point of line to erase
LineTo(hdcPctrBox, xEndErase, yEndErase); //end point of line to erase
(code continues...)
To delete your resources:
HPEN hLinePen = NULL, hLinePenErase = NULL, originalPen = NULL;
HDC hdcPctrBox = NULL;
hdcPctrBox = GetWindowDC(hwndPctrBox); //hwndPctrBox is the handle of picturebox
originalPen = SelectObject(hdcPctrBox, GetStockObject(DC_PEN));
//create the two pens
//in the end release resources
SelectObject(hdcPctrBox, originalPen);
DeleteObject(hLinePen);
DeleteObject(hLinePenErase);
ReleaseDC(hwndPctrBox, hdcPctrBox);
valter
I suggest to implement your own painting class. Derive your own class from "Panel" or "UserControl" and do the following in the constructor, which activates double buffering and optimized drawing:
public ref class MyPaintControl : public System::Windows::Forms::UserControl
{
public:
MyPaintControl()
{
this->SetStyle(System::Windows::Forms::ControlStyles::AllPaintingInWmPaint, true);
this->SetStyle(System::Windows::Forms::ControlStyles::DoubleBuffer, true);
this->SetStyle(System::Windows::Forms::ControlStyles::ResizeRedraw, true);
this->SetStyle(System::Windows::Forms::ControlStyles::UserPaint, true);
}
// And then implement your painting in OnPaint:
protected:
virtual void OnPaint(PaintEventArgs^ e)
{
// Do painting...
System::Drawing::Brush^ br = gcnew System::Drawing::SolidBrush(this->BackColor);
e->Graphics->FillRectangle(br, this->ClientRectangle);
delete br;
// Do other paintings...
}
// This function might be called if new data arrived...
public:
void UpdateArea(int daten) // pass data here, if you want...
{
// Store the data in a member variable...
// force a redraw:
this->InvalidateRect(); // this will force a "OnPaint"
}
}
Then embedd this control in your UI. This should improve your painting very much!
Also this works, even if you move or resize your window. Be aware, that painting should always be done in "OnPaint"!
I would like to update the state of my coding.
I used the method posted by Jochen. It is very fast but it does not suit my application or maybe I'm not able to adapt it. What I need to do, is to update constantly my plot. At time t0, I should draw a line. At time t1, when I store a new line, I should draw the new line and add this to the previous one. The plot must be "alive". I tried to derive a panel class and override the OnPaintevent but my plot refreshing only if all lines are stored and displayed.

Resources