PDA

Ver la Versión Completa : Canvas Does Not Allow Drawing


ebeltete
09-07-2003, 19:39:52
Por que me aparece este mensaje cuando tengo determinadas aplicaciones abiretas al mismo tiempo, si ejecuto solo mi aplicacion no tengo problema pero si tengo abierto el Kazaa me aparece este mensaje

andres1569
10-07-2003, 01:08:27
¿Sobre qué versión de Windows trabajas?.

Este error se lanza únicamente cuando un objeto TCanvas no puede crear un Handle sobre el que dibujar. En otras palabras, si tienes los recursos del sistema bajo mínimos es muy probable que Windows no permita asignar más Handles, y cuando un objeto que necesita dibujarse a través de Un TCanvas lo solicita, Windows se lo deniega, de ahí ese error.

Esto es más común en un sistema Win95 o Win98; en Win2000 los recursos del GDI tienen un límite bastante mayor. A mí me ha aparecido bastantes veces este error bajo Win98 teniendo abierto el IDE de Delphi con varios formularios que contiene gran cantidad de componentes gráficos; si ejecuto sin cerrar el IDE o sin cerrar dichos formularios, los recursos disminuyen de lo lindo.

Habría que ver cuántos recursos GDI consume esa otra aplicación, el Kazaa que comentas, cuando digo recursos GDI me refiero a Cursores, Bitmaps, Fuentes etc... No lo vas a solucionar metiendo más RAM, pues es un límite que tiene el sistema operativo.

ebeltete
10-07-2003, 02:44:10
Estoy trabajando con Windows 98, pero lo raro es que cambie de maquina y me empezo a suceder, antes tenia menos memoria y una maquina mas lenta y no me pasaba, no hay forma de cambiar esa configuracion en Win98?

andres1569
10-07-2003, 11:59:43
Quizás los programas que tenías en la máquina vieja no consumían tantos recursos GDI. Ya digo que es algo propio del SO, y creo que es intocable, no creo que se pueda ajustar esos límites desde el registro ni nada similar, sería un riesgo para Windows.

delphi.com.ar
10-07-2003, 17:03:02
Agrego que es un error MUY COMÚN cuando escasean los recursos, y por eso te ha pasado cuando empezaste a ejecutar tu aplicación en otro equipo, que seguramente tiene una configuración diferente al equipo donde desarrollaste la aplicación.
Este error, como dice Andrés, sucede cuando TCanvas no puede crear un Handle, y esto sucede cuando Windows le "niega" la creación del nuevo Handle para ese canvas porque llegó al tope de los recursos.

Te recomiendo leer este hilo, donde hablo de como "ahorrar" recursos en aplicaciones grandes:
http://www.clubdelphi.com/foros/showthread.php?s=&threadid=253

Saludos!

ebeltete
28-08-2003, 01:04:24
Puede ser que el problema sea porque en el timage tengo archivos jpg???? antes tenia bmp y no me daba error, lo cambie a jpg para "achicar" el ejecutable, tal vez sea eso????

Me pasa lo mismo en una pequeña aplicación!!!

delphi.com.ar
28-08-2003, 04:38:38
Te en cuenta que si trabajas con Jpegs, achicarás tu aplicación en recursos pero incrementarás la cantidad de código, pues tienes que introducir todos los algoritmos de Jpegs. Si los bitmaps son pequeños yo los dejaría como bitmaps.

Saludos!

ebeltete
14-06-2004, 23:33:11
Vuelvo al foro porque este tema me tiene bastante confundido, agradezco y entiendo vuestras explicaciones pero sospecho que algo tiene que ver mi aplicacion, pues me pasa en varias pc's cuando ejecuto mi aplicacion, no siempre pero si a veces, y el factor comun es MI APLICACION ; puede ser algo en la forma de pintar las ventanas?, también tengo unos DBGRIDS con codigo en el evento "DrawColumnCell", puede ser algo de eso?
Gracias

andres1569
16-06-2004, 13:05:39
... también tengo unos DBGRIDS con codigo en el evento "DrawColumnCell", puede ser algo de eso?Mira si en dicho código creas alguna instancia de la clase TBitmap y luego no la destruyes. Los bitmaps consumen Handles de Windows.

ebeltete
22-06-2004, 06:22:38
El codigo es algo como esto:

private
{ Private declarations }
UnColor:TColor;


procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if DataCol=0 then
if Table1Size.AsInteger>10
then UnColor:=clRed
else UnColor:=clBlack;

with (Sender As TDBGrid).Canvas do
begin
Font.Color:=UnColor;
FillRect(Rect);
TextOut(Rect.Left, Rect.Top, Column.Field.AsString);
end;
end;

andres1569
22-06-2004, 18:32:01
Hola:

En el código que mencionas, resulta evidente que no puede haber una pérdida de memoria/recursos. Mira si utilizas componentes de terceros que pudieran causar dicho consumo exagerado y ten en cuenta que no tiene por qué haber un fallo de programación (el no liberar los recursos u objetos que los consuman) para que los recursos caigan tan bajo, eso sería si al cerrar la aplicación no se restituyeran, simplemente si tu aplicación hace un uso intensivo de los mismos, ya puede ser causa de el error que te sucede.

La filosofía del programa también influye, no es lo mismo que muestres formularios bajo demanda y los destruyas cuando ya no hacen falta, que por ejemplo muestres un form principal con tropecientos controles, por ejemplo divididos en un TabbedBook. Mira también de utilizar TImagesList para concentrar las imágenes en un sólo sitio, en vez de asignar Glyphs a diestro y siniestro (cada uno es un Bitmap diferente) si te es posible.

Bueno, son algunas ideas ...

Saludos

ebeltete
17-06-2005, 00:51:54
Sigo en esto , encontre un comentario en otro foro (http://www.softwaremix.net/viewtopic-394770.html) que habla de este tema, veo que estoy mal al autocrear los form de mi aplicacion, pense que delphi solucionaba esto, pero no basta con mostrarlos (form1.show) sino que me conviene crearlos y en el evento onclose destruirlo, esa puede ser un solucion?
Salu2

roman
17-06-2005, 01:02:10
Oooorale! Revives este hilo cada año :eek:

Y ¿no será culpa del Kazaa?

// Saludos

roman
17-06-2005, 01:14:49
Oye, leyendo el enlace que pusiste me surge la pregunta: ¿El error te aparece apenas corres la aplicación o es como describen ahí, que ocurre después de un rato de estar usándola? Porque de ser así, muy probablemente se trate de una fuga de memoria, objetos que no se destruyen correctamente dejando pedazos de memoria inutilizables. Para estas cosas a mi me ha servido mucho programas como MemProof (http://www.automatedqa.com/downloads/memproof/) que lo corres junto a tu aplicación y te dice en qué partes hay recursos que no se liberan.

// Saludos

ebeltete
17-06-2005, 19:17:00
Gracias Roman, el error no me aparece siempre, pero cuando lo hace es al abrir mi aplicacion, y cuando tengo muchos programas abiertos, creo sea porque las ventanas se crean al iniciar la aplicacion, ahora estoy probando en crear los forms a medida que los voy utilizando, pero se me ha complicado porque tenia referencias de unos forms a otros, tambien voy a probar con memproof, gracias y seguire investigando.

<Sergio>
19-06-2005, 23:33:43
Oooorale! Revives este hilo cada año :eek:

Y ¿no será culpa del Kazaa?

// Saludos Pues yo creo que si. A mi también me dio problemas. (Otro "tragón" de recursos es el messenger.):mad:

Bueno, buscando en los enlaces posteados, di con:


if Win32Platform = VER_PLATFORM_WIN32_NT then
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);


( Codigo que sirve para ceder cordialmente la RAM que no estás utilizando (lo que no hace el Kazaa) y cambiarla por virtual )

Si buscan en la ayuda:

SetProcessWorkingSetSize();

Verán que utilizar este comando en forma grosera es la causa que una aplicación luego no tenga suficiente espacio para trabajar y seguramente que asi lo hacen programas como el Kazaa.

También puede ayudar utilizar "Tbitmap.Dormant" para usar memoria del sistema en lugar de recursos de GDI y también indicar que queremos el bitmap como "device independer bitmap" "HandleType:=bmDIB".

P.D.

Uso el emule. :D

ebeltete
20-06-2005, 03:28:29
como es la historia de imagelist?
Mi aplicacion no tiene muchas imagenes, solo algunos timage y algunos tspeedbuttons con sus glyph, es lo mismo asignarle los bitmap directamente en la propiedad glyph de los speedbutons y en la propiedad picture del timage , o es mejor poner todos los bitmap en un imagelist y "sacarlos" del imagelist para ponerlos en los speedbuttons? si es asi como se hace, no lo tengo muy claro, gracias.

<Sergio>
21-06-2005, 15:57:36
El Timagelist utilizalo si tienes imágenes repetidas en tus botones. Ej 10 ventanas todas con 2 botones con los mismos gráficos, en cada ventana. Con esto se reducen los "handles" necesarios en el ejemplo de 20 a 2.

Una pregunta

¿Cuanto ocupa tu .exe? (Como esos bitmaps son incluidos dentro del .exe es para tener una idea de cuanto espacio están ocupando tus bitmaps)

ebeltete
21-06-2005, 18:59:27
Mi ejecutable es de 2.16 MB, es una aplicacion que maneja bases de datos paradox, y esta hecho en Delphi 5, nunca le di pelota al tema de los recursos, de hecho el programa funciona bien, pero..., siempre es bueno optimizar los recursos, y generalmente cuando estoy trabajando en el con Delphi y trato de abrirlo me produce ese error, muchas veces tengo que cerrar Delphi y ejecutarlo para probarlo, esto se me hace fastidioso por todo lo que significa, otra pregunta, como le asigno la imagen desde un imagelist al glyph de un speedbutton, puedo hacer algo como esto: speedbutton2.glyph:=speedbutton1.glyph, esto me reduce la cantidad de bitmap?
Gracias y un abrazo.

roman
21-06-2005, 19:05:55
Aunque lo del ImageList puede ser útil por otras razones, dudo que te vaya a servir de algo para tu problema.

¿Ya probaste lo del MemProof?
¿Tienes componentes de terceros?
¿Has probado cambiando las imágenes? Quizá bajando la resolución o el número de colores.

// Saludos

<Sergio>
26-06-2005, 01:31:35
Mi ejecutable es de 2.16 MB, es una aplicacion que maneja bases de datos paradox, y esta hecho en Delphi 5, nunca le di pelota al tema de los recursos, de hecho el programa funciona bien, pero..., siempre es bueno optimizar los recursos, y generalmente cuando estoy trabajando en el con Delphi y trato de abrirlo me produce ese error, muchas veces tengo que cerrar Delphi y ejecutarlo para probarlo, esto se me hace fastidioso por todo lo que significa, otra pregunta, como le asigno la imagen desde un imagelist al glyph de un speedbutton, puedo hacer algo como esto: speedbutton2.glyph:=speedbutton1.glyph, esto me reduce la cantidad de bitmap?
Gracias y un abrazo.
2.16 MB hmmm pues tus bmp son relativamente chicos y no es problema de resolución de tus bmp.

Como ya indico Roman, revisalo con el memproof por que también revisa esas cuestiones de recursos gráficos. A mi me ayudo a encontrar un bug de liberación de memoria por culpa de un "destroy" que estaba en "private" y no en "protected" donde debería estar.

Aunque esto no solucionará tu problema, es bueno tener un compresor de .exe : ¿o ya usaste uno para reducir de tamaño tu .exe?

The Ultimate Packer for eXecutables
Copyright (c) 1996-2004 Markus Oberhumer & Laszlo Molnar
http://upx.sourceforge.net

PabloTech
15-01-2007, 17:07:25
Como bien dijo andrés1569:
Este error se lanza únicamente cuando un objeto TCanvas no puede crear un Handle sobre el que dibujar. En otras palabras, si tienes los recursos del sistema bajo mínimos es muy probable que Windows no permita asignar más Handles, y cuando un objeto que necesita dibujarse a través de Un TCanvas lo solicita, Windows se lo deniega, de ahí ese error.
Mi sistema ya pasa los 4MB y el error me aparecía de vez en cuando. Tengo una ventana con dos grillas enlazadas como maestro-detalle y un reporte que se cargaba, a veces un 1%, un 15% o un 25%, siempre aleatoriamente. Los datos los obtengo de PostgresSQL. Vi sus hipótesis y son acertadas. La solución que me dió excelente resultado es deshabilitar los controles asociados a los datos (o sea las grillas) antes de ver o imprimir el reporte. Ejemplo:

ModuloDatos.t_Clientes.DisableControls;
...
r_Listado.Print; // o r_Listado.PreviewModal;
...
ModuloDatos.t_Clientes.EnableControls;

Espero que les sirva como a mi.