Problema con el GDI

30/01/2004 - 03:16 por Juan Antonio | Informe spam
Hola de nuevo grupo,

Comento un poco lo que que quiero hacer:

tengo una aplicación que hace un seguimiento de un tren
en una maqueta. cuando pulso un boton del menu empiezo a
recibir se ejecuta una funcion muchas veces por segundo
gracias a un timer, consiguiendo imagenes de una webcam,
y de estas imagenes mediante un algoritmo saco las
coordenadas de la locomotora.

necesito crear una ventana dentro del area cliente donde
visualiazar un archivo bmp que es como un mapa de las
vias, y a continuación dibujar un punto con las
coordenadas.

proceso que quiero hacer:

1-> al pulsar el boton de comenzar, quiero crear la
ventana en la que visualizo el bmp y dibujo el punto.
tambien debo cargar el bmp en memoria en un hbitmap
porque el acceso a .bmp es lento y necesito rapidez.

2->al pulsar el boton anterior se ejecuta una funcion
varias veces por segundo mediante un timer. en esta
función quiero actualizar el bmp(para eliminar el punto
de la llamada anterior) y pintar el punto en las
coordenadas obtenidas.

3->al pulsar el boton de terminar eliminar la ventana
creada.

1 y 3 me funcionan bien, el problema lo tengo en 2 creo.
voy a explicar lo k hago en cada paso.

//********************1***************************

asi creo la ventana:

void CreateWindowResultado (void)

{

WNDCLASS WndClass;

WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.lpfnWndProc =(WNDPROC)MainWndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE
+ 1);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInstanceGlobal;
WndClass.lpszClassName = "DESTINE_CLASE";
WndClass.lpszMenuName = NULL;

//se registra la clase
RegisterClass(&WndClass);

//se crea la ventana
hWndResultado = CreateWindow(

"DESTINE_CLASE",

"",

WS_POPUPWINDOW|WS_VISIBLE,

4,

309,

322,

242,

hwnd,

NULL,

hInstanceGlobal,>variable global

NULL

);



}

asi cargo el bmp:

hBitmapMapa = (HBITMAP)LoadImage
(hInstanceGlobal,"patronviafinal164.bmp",
IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

hBitmapMapa lo tengo como variable global


//********************2***************************

asi actualizo el bmp:

se ejecuta con cada iteracion del timer

void UpdateWndResultado (void)

{

HDC hDc = NULL;
HDC Compatible = NULL;

HBITMAP old_hBitmap = NULL;
HBITMAP hBitmapMapaCopia = NULL;

//se copia el original(variable global) en la
copia

hBitmapMapaCopia = hBitmapMapa;

//se obtiene un DC de la ventana de resultado

hDc = GetDC( hWndResultado );

//se crea uno compatible con el anterior

Compatible = CreateCompatibleDC(hDc);

//se selecciona el último

old_hBitmap = (HBITMAP)SelectObject( Compatible,
hBitmapMapaCopia);

//se actualiza la ventana
BitBlt(hDc,0,0,320,240,Compatible,0,0,SRCCOPY);

//liberan objetos y DCs

SelectObject(Compatible,old_hBitmap);

DeleteObject(hBitmapMapaCopia);

ReleaseDC(hWndResultado, hDc);

DeleteDC(Compatible);


}




y ahora como dibujo el punto:

se realiza con cada iteracion del timer

HDC hDC;
PAINTSTRUCT ps;
HBRUSH hBrush, hOldBrush;
hDC = BeginPaint(hWndResultado, &ps);
hBrush = CreateSolidBrush(RGB(240,0,0));
hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);
Ellipse(hDC, 10, 10, 20, 20);
SelectObject(hDC, hOldBrush);
DeleteObject(hBrush);
EndPaint(hwnd, &ps);

en principio las coordenadas estan puestas fijas para
probar.


con el 3 no hay problemas un DestroyWindow y listo.



*****************problemas****************************

si pulso en comenzar aparece el .bmp en la ventana que he
creado, pero no me sale el punto rojo, y no es problema
de colores, son distintos, y si minimizo la aplicacion y
la restauro ya no me sale el bmp, entonces aparece el
punto rojo solo.


siento mucho el rollazo que he metido.

un saludo,
Juan Antonio.

Preguntas similare

Leer las respuestas

#1 Hernán
30/01/2004 - 04:58 | Informe spam
"Juan Antonio" escribía,

Hola de nuevo grupo,

Comento un poco lo que que quiero hacer:



[...]
2->al pulsar el boton anterior se ejecuta una funcion
varias veces por segundo mediante un timer. en esta
función quiero actualizar el bmp(para eliminar el punto
de la llamada anterior) y pintar el punto en las
coordenadas obtenidas.




este sería el timer:
InvalidateRect(..., TRUE) // rect del punto viejo
NuevaPosicionPunto()
InvalidateRect(..., TRUE) // rect del nuevo punto

este el erase background para el caso de que el mapa ocupe todo el fondo
del radar:
return (LRESULT)TRUE;

este es tu paint:
BeginPaint(..., &ps)
PintaMapa(ps.hdc, ...) // igual que UpdateWndResultado()
PintaPunto(ps.hdc, ...) // Ellipse(..., coord del nuevo punto)
EndPaint()

[...]

Hernán (27)
Quilmes (ar)
Respuesta Responder a este mensaje
#2 Juan Antonio
30/01/2004 - 20:39 | Informe spam
¿te refieres que ponga el invalidaterect antes de aplicar
el algoritmo, y al acabarlo lo aplico de nuevo?¿los dos
con true como parámetro?

este sería el timer:
InvalidateRect(..., TRUE) // rect del punto viejo
NuevaPosicionPunto()
InvalidateRect(..., TRUE) // rect del nuevo punto



¿esto lo hago en el mensaje WM_ERASEBKGND si el mensaje
viene de la ventana donde visualizo el bitmap y el punto?

este el erase background para el caso de que el mapa


ocupe todo el fondo
del radar:
return (LRESULT)TRUE;




¿y esto va en el mensaje wm_paint?
este es tu paint:
BeginPaint(..., &ps)
PintaMapa(ps.hdc, ...) // igual que


UpdateWndResultado()
PintaPunto(ps.hdc, ...) // Ellipse(..., coord del


nuevo punto)
EndPaint()



lo siento es que no conozco mucho la filosofia de
funcionamiento del GDI.

un saludo.
Respuesta Responder a este mensaje
#3 Hernán
31/01/2004 - 00:41 | Informe spam
"Juan Antonio" escribía,

¿te refieres que ponga el invalidaterect antes de aplicar
el algoritmo, y al acabarlo lo aplico de nuevo?¿los dos
con true como parámetro?




Lo que decía es que no debes pintar en el timer. Que uses el timer para
actualizar las coordenadas del punto, si cabe, y para invalidar las
regiones de la pantalla que necesitarán modificación durante el próximo
llamado a WM_PAINT, que vos no controlás.

InvalidateRect() permite preparar el DC de la pantalla relativo a la
ventana. Entonces vos usás el hdc contenido en el PAINTSTRUCT llenado
por BeginPaint(), en lugar de llamar a GetDC().

El TRUE hace que BeginPaint() envíe un WM_ERASEBKGND.

Si vos mandas en el timer directamente un InvalidateRect(hwnd, NULL,
TRUE), toda la ventana será repintada. Es más fácil pero es un
desperdicio cuando vos sólo necesitas repintar dos cuadritos de 10x10.

Ah, se me había pasado, si vos cargás el bitmap al comienzo (una sola
vez), entonces no lo descargues con DeleteObject(hBitmapMapaCopia), cada
vez que pintes. Al handle y la memoria asociada, la liberás de esa
manera pero cuando ya no uses más el hbitmap. Digamos durante el
WM_DESTROY.

Hernán (27)
Quilmes (ar)
Respuesta Responder a este mensaje
#4 Juan Antonio
31/01/2004 - 04:11 | Informe spam
ok gracias, al final lo consegui pero necesitaba rapidez aproximadamente tengo que hacerlo 25 veces por segundo, y el GDI y el mensaje WM_PAINT creo que son lentos, entonces me decidi por usar DrawDib de la biblioteca mmsystem y no lo consegui del todo lo que queria. Al final lo solucione usando la misma biblioteca de las funciones de visión artificial, las Mil seguro que os sonarán

Un saludo.
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida