View previous topic :: View next topic |
Author |
Message |
jvr
Joined: 19 Nov 2007 Posts: 10
|
Posted: Wed Dec 19, 2007 12:03 pm Post subject: DCs |
|
|
Hi,
There is a problem in DFL with the device contexts (DC) in Win95/98/ME, the DCs should be created just before any painting operation and released immediately.
It's a source of problems to create a DC and save it as a class member.
It seems that -at least- MemoryGraphics/Graphics creates the DC in its constructor and release it in the destructor, this works in NT/2K/XP but it doesn't work in Win9x, (play with one or two dozens of MemoryGraphics in Win9x and you'll see the effects).
This is not a problem in 2K/NT/XP (it only happens in extreme cases), but in Win9x/ME the DCs are very limited;
from MSDN: "Windows 95/98/Me: There are only 5 common DCs available per thread, thus failure to release a DC can prevent other applications from accessing one".
http://msdn2.microsoft.com/en-us/library/ms533241.aspx
Cheers,
Javi |
|
Back to top |
|
|
Chris Miller
Joined: 27 Mar 2004 Posts: 514 Location: The Internet
|
Posted: Wed Dec 19, 2007 2:32 pm Post subject: Re: DCs |
|
|
The Graphics objects are "scope" allocated, which means they are destructed once execution leaves its scope, which should be sufficient. Did you run into real problems? I've tested DFL on Windows 9x in the past and the DCs were fine. |
|
Back to top |
|
|
jvr
Joined: 19 Nov 2007 Posts: 10
|
Posted: Wed Dec 19, 2007 4:18 pm Post subject: Re: DCs |
|
|
Yes, I've programmed a class of skin buttons, and each object has 4 MemoryGraphics (to hold the generated button images of up, down, selected and disabled), in the mouse event functions -mouseEnter, mouseDown, etc.- these images are copied (copyTo()) to the PictureBox that represents each button. It runs perfectly on XP but in Win9x there are no enough free DCs and only 3 o 4 buttons are displayed correctly.
Here you have the source code if you want to check it:
Code: |
module skinbutton;
import dfl.all;
class SkinButton
{
private:
const char[] RESOURCE_STR = "SKINBUTTON_";
PictureBox m_picbox;
Graphics m_picbox_gfx;
MemoryGraphics m_mem_gfx_up;
MemoryGraphics m_mem_gfx_down;
MemoryGraphics m_mem_gfx_high;
MemoryGraphics m_mem_gfx_disable;
bool m_enable;
int m_width;
int m_height;
Font m_font;
char[] m_text;
Icon m_icon;
char[] m_icon_name;
uint m_icon_pos;
void delegate() m_callback_click;
bool m_keep_pushed;
void Paint(Object sender, EventArgs ea)
{
// Repintar el boton pulsado o normal, activado/desactivado?
if(m_keep_pushed)
{
if(m_enable)
{
m_mem_gfx_down.copyTo(m_picbox_gfx, 0, 0, m_width, m_height);
}
else
{
m_mem_gfx_disable.copyTo(m_picbox_gfx, 0, 0, m_width, m_height);
}
}
else
{
if(m_enable)
{
m_mem_gfx_up.copyTo(m_picbox_gfx, 0, 0, m_width, m_height);
}
else
{
m_mem_gfx_disable.copyTo(m_picbox_gfx, 0, 0, m_width, m_height);
}
}
}
void MouseEnter(Object sender, EventArgs ea)
{
// Poner imagen high si el boton no esta pulsado y esta activado
if(!m_keep_pushed && m_enable)
{
m_mem_gfx_high.copyTo(m_picbox_gfx, 0, 0, m_width, m_height);
}
}
void MouseLeave(Object sender, EventArgs ea)
{
// Poner imagen up si el boton no esta pulsado y esta activado
if(!m_keep_pushed && m_enable)
{
m_mem_gfx_up.copyTo(m_picbox_gfx, 0, 0, m_width, m_height);
}
}
void MouseDown(Object sender, EventArgs ea)
{
// Poner imagen down al pulsar el boton
if(m_enable && (cast(MouseEventArgs)ea).button == MouseButtons.LEFT)
{
m_mem_gfx_down.copyTo(m_picbox_gfx, 0, 0, m_width, m_height);
}
}
void MouseUp(Object sender, EventArgs ea)
{
// Llamar a la funcion si el boton esta activado
if(m_callback_click !is null && m_enable && (cast(MouseEventArgs)ea).button == MouseButtons.LEFT)
{
m_callback_click();
}
// Poner imagen high si el boton no esta pulsado y esta activado,
// y si el puntero del raton sigue encima del boton.
Point mouse = m_picbox.pointToClient(m_picbox.mousePosition());
if(!m_keep_pushed && m_enable && (cast(MouseEventArgs)ea).button == MouseButtons.LEFT &&
mouse.x < m_width && mouse.y < m_height)
{
m_mem_gfx_high.copyTo(m_picbox_gfx, 0, 0, m_width, m_height);
}
}
public:
this(char[] text, Control parent, void delegate() on_click, Rect bounds,
uint resource_button=0, char[] resource_icon=null, uint icon_pos=0,
Font font=null, bool enable=true, bool keep_pushed=false)
{
// Nombre inicial de los bmps de recurso a cargar
char[] resource_bmps = RESOURCE_STR ~ std.string.toString(resource_button) ~ "_";
// Funcion callback de click
m_callback_click = on_click;
// Mantener pulsado?
m_keep_pushed = keep_pushed;
// Estado
m_enable = enable;
// Icono?
m_icon_name = resource_icon;
m_icon_pos = icon_pos; // 0 arriba, 1 izquierda
if(m_icon_name !is null)
{
m_icon = Application.resources.loadIcon(m_icon_name);
}
// Fuente
if(font is null)
{
// Fuente standard
m_font = new Font("MS Sans Serif", 9f, FontStyle.REGULAR);
}
else
{
m_font = font;
}
m_text = text;
// Crear PictureBox
m_picbox = new PictureBox();
m_picbox.name = "SkinButton";
m_picbox.bounds = bounds;
m_picbox.parent = parent;
// Crear bitmaps del boton
m_picbox_gfx = m_picbox.createGraphics();
m_width = m_picbox.width;
m_height = m_picbox.height;
m_mem_gfx_up = new MemoryGraphics(m_width, m_height);
m_mem_gfx_down = new MemoryGraphics(m_width, m_height);
m_mem_gfx_high = new MemoryGraphics(m_width, m_height);
m_mem_gfx_disable = new MemoryGraphics(m_width, m_height);
/*------------------------------------------------------------
Boton normal (UP)
------------------------------------------------------------*/
// Rellenar bitmap borde superior
Bitmap bmp = Application.resources.getBitmap(resource_bmps ~ "UP_UP");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_up, Point(x, 0));
}
// Rellenar bitmap central
int up_bmp_h = bmp.height;
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_CENTER");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_up, Point(x, up_bmp_h));
}
// Rellenar bitmap borde inferior
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_DOWN");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_up, Point(x, m_height-bmp.height));
}
// Rellenar bitmap borde izquierdo
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_LEFT");
for(uint y=0; y < m_height; y++)
{
bmp.draw(m_mem_gfx_up, Point(0, y));
}
// Rellenar bitmap borde derecho
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_RIGHT");
for(uint y=0; y < m_height; y++)
{
bmp.draw(m_mem_gfx_up, Point(m_width-bmp.width, y));
}
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_UP_LEFT");
bmp.draw(m_mem_gfx_up, Point(0, 0));
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_UP_RIGHT");
bmp.draw(m_mem_gfx_up, Point(m_width-bmp.width, 0));
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_DOWN_RIGHT");
bmp.draw(m_mem_gfx_up, Point(m_width-bmp.width, m_height-bmp.height));
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_DOWN_LEFT");
bmp.draw(m_mem_gfx_up, Point(0, m_height-bmp.height));
// Medidas del texto
Size ts = m_mem_gfx_up.measureText(m_text, m_font);
uint tx = (m_width-ts.width)/2;
uint ty = (m_height-ts.height)/2;
// Icono?
if(m_icon_name !is null)
{
switch(m_icon_pos)
{
case 0:
// Icono arriba
uint ix = (m_width-m_icon.width)/2;
uint iy = (m_height-m_icon.height)/2 - ts.height/2 - 2;
m_mem_gfx_up.drawIcon(m_icon, ix, iy);
m_mem_gfx_up.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx, ty+ty/2+4, ts.width, ts.height));
break;
case 1:
// Icono a la izquierda
uint ix = m_width/12;
uint iy = (m_height-m_icon.height)/2;
m_mem_gfx_up.drawIcon(m_icon, ix, iy);
m_mem_gfx_up.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx+m_icon.width/2, ty, ts.width, ts.height));
break;
}
}
else
{
// Dibujar solo texto centrado
m_mem_gfx_up.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx, ty, ts.width, ts.height));
}
/*------------------------------------------------------------
Boton pulsado (DOWN)
------------------------------------------------------------*/
// Rellenar bitmap borde superior
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_UP");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_down, Point(x, 0));
}
// Rellenar bitmap central
up_bmp_h = bmp.height;
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_CENTER");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_down, Point(x, up_bmp_h));
}
// Rellenar bitmap borde inferior
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_DOWN");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_down, Point(x, m_height-bmp.height));
}
// Rellenar bitmap borde izquierdo
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_LEFT");
for(uint y=0; y < m_height; y++)
{
bmp.draw(m_mem_gfx_down, Point(0, y));
}
// Rellenar bitmap borde derecho
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_RIGHT");
for(uint y=0; y < m_height; y++)
{
bmp.draw(m_mem_gfx_down, Point(m_width-bmp.width, y));
}
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_UP_LEFT");
bmp.draw(m_mem_gfx_down, Point(0, 0));
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_UP_RIGHT");
bmp.draw(m_mem_gfx_down, Point(m_width-bmp.width, 0));
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_DOWN_RIGHT");
bmp.draw(m_mem_gfx_down, Point(m_width-bmp.width, m_height-bmp.height));
bmp = Application.resources.getBitmap(resource_bmps ~ "DOWN_DOWN_LEFT");
bmp.draw(m_mem_gfx_down, Point(0, m_height-bmp.height));
// Icono?
if(m_icon_name !is null)
{
switch(m_icon_pos)
{
case 0:
// Icono arriba
uint ix = (m_width-m_icon.width)/2;
uint iy = (m_height-m_icon.height)/2 - ts.height/2 - 2;
m_mem_gfx_down.drawIcon(m_icon, ix+1, iy+1);
m_mem_gfx_down.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx+1, ty+ty/2+4+1, ts.width, ts.height));
break;
case 1:
// Icono a la izquierda
uint ix = m_width/12;
uint iy = (m_height-m_icon.height)/2;
m_mem_gfx_down.drawIcon(m_icon, ix+1, iy+1);
m_mem_gfx_down.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx+m_icon.width/2+1, ty+1, ts.width, ts.height));
break;
}
}
else
{
// Dibujar solo texto centrado
m_mem_gfx_down.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx+1, ty+1, ts.width, ts.height));
}
/*------------------------------------------------------------
Boton resaltado (HIGH)
------------------------------------------------------------*/
// Rellenar bitmap borde superior
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_UP");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_high, Point(x, 0));
}
// Rellenar bitmap central
up_bmp_h = bmp.height;
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_CENTER");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_high, Point(x, up_bmp_h));
}
// Rellenar bitmap borde inferior
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_DOWN");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_high, Point(x, m_height-bmp.height));
}
// Rellenar bitmap borde izquierdo
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_LEFT");
for(uint y=0; y < m_height; y++)
{
bmp.draw(m_mem_gfx_high, Point(0, y));
}
// Rellenar bitmap borde derecho
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_RIGHT");
for(uint y=0; y < m_height; y++)
{
bmp.draw(m_mem_gfx_high, Point(m_width-bmp.width, y));
}
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_UP_LEFT");
bmp.draw(m_mem_gfx_high, Point(0, 0));
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_UP_RIGHT");
bmp.draw(m_mem_gfx_high, Point(m_width-bmp.width, 0));
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_DOWN_RIGHT");
bmp.draw(m_mem_gfx_high, Point(m_width-bmp.width, m_height-bmp.height));
bmp = Application.resources.getBitmap(resource_bmps ~ "HIGH_DOWN_LEFT");
bmp.draw(m_mem_gfx_high, Point(0, m_height-bmp.height));
// Icono?
if(m_icon_name !is null)
{
switch(m_icon_pos)
{
case 0:
// Icono arriba
uint ix = (m_width-m_icon.width)/2;
uint iy = (m_height-m_icon.height)/2 - ts.height/2 - 2;
m_mem_gfx_high.drawIcon(m_icon, ix, iy);
m_mem_gfx_high.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx, ty+ty/2+4, ts.width, ts.height));
break;
case 1:
// Icono a la izquierda
uint ix = m_width/12;
uint iy = (m_height-m_icon.height)/2;
m_mem_gfx_high.drawIcon(m_icon, ix, iy);
m_mem_gfx_high.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx+m_icon.width/2, ty, ts.width, ts.height));
break;
}
}
else
{
// Dibujar solo texto centrado
m_mem_gfx_high.drawText(m_text, m_font, Color(0, 0, 0), Rect(tx, ty, ts.width, ts.height));
}
/*------------------------------------------------------------
Boton desactivado (DISABLE)
------------------------------------------------------------*/
// Rellenar bitmap borde superior
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_UP");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_disable, Point(x, 0));
}
// Rellenar bitmap central
up_bmp_h = bmp.height;
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_CENTER_DISABLE");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_disable, Point(x, up_bmp_h));
}
// Rellenar bitmap borde inferior
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_DOWN");
for(uint x=0; x < m_width; x++)
{
bmp.draw(m_mem_gfx_disable, Point(x, m_height-bmp.height));
}
// Rellenar bitmap borde izquierdo
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_LEFT");
for(uint y=0; y < m_height; y++)
{
bmp.draw(m_mem_gfx_disable, Point(0, y));
}
// Rellenar bitmap borde derecho
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_RIGHT");
for(uint y=0; y < m_height; y++)
{
bmp.draw(m_mem_gfx_disable, Point(m_width-bmp.width, y));
}
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_UP_LEFT");
bmp.draw(m_mem_gfx_disable, Point(0, 0));
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_UP_RIGHT");
bmp.draw(m_mem_gfx_disable, Point(m_width-bmp.width, 0));
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_DOWN_RIGHT");
bmp.draw(m_mem_gfx_disable, Point(m_width-bmp.width, m_height-bmp.height));
bmp = Application.resources.getBitmap(resource_bmps ~ "UP_DOWN_LEFT");
bmp.draw(m_mem_gfx_disable, Point(0, m_height-bmp.height));
// Medidas del texto
ts = m_mem_gfx_disable.measureText(m_text, m_font);
tx = (m_width-ts.width)/2;
ty = (m_height-ts.height)/2;
// Icono?
if(m_icon_name !is null)
{
switch(m_icon_pos)
{
case 0:
// Icono arriba
uint ix = (m_width-m_icon.width)/2;
uint iy = (m_height-m_icon.height)/2 - ts.height/2 - 2;
m_mem_gfx_disable.drawIcon(m_icon, ix, iy);
m_mem_gfx_disable.drawText(m_text, m_font, Color(120, 120, 120), Rect(tx, ty+ty/2+4, ts.width, ts.height));
break;
case 1:
// Icono a la izquierda
uint ix = m_width/12;
uint iy = (m_height-m_icon.height)/2;
m_mem_gfx_disable.drawIcon(m_icon, ix, iy);
m_mem_gfx_disable.drawText(m_text, m_font, Color(120, 120, 120), Rect(tx+m_icon.width/2, ty, ts.width, ts.height));
break;
}
}
else
{
// Dibujar solo texto centrado
m_mem_gfx_disable.drawText(m_text, m_font, Color(120, 120, 120), Rect(tx, ty, ts.width, ts.height));
}
// Empezar por mostrar el boton pulsado o normal, activado/desactivado?
Paint(null, null);
// Asignar funcion de repintado
m_picbox.paint ~= &Paint;
// Control de eventos del raton
m_picbox.mouseEnter ~= &MouseEnter;
m_picbox.mouseLeave ~= &MouseLeave;
m_picbox.mouseDown ~= &MouseDown;
m_picbox.mouseUp ~= &MouseUp;
}
void KeepPushed(bool keep_pushed)
{
m_keep_pushed = keep_pushed;
Paint(null, null);
}
bool IsKeepPushed()
{
return(m_keep_pushed);
}
void Enable(bool enable)
{
m_enable = enable;
Paint(null, null);
}
bool IsEnable()
{
return(m_enable);
}
void Visible(bool visible)
{
m_picbox.visible = visible;
}
bool IsVisible()
{
return(m_picbox.visible());
}
PictureBox GetPictureBox()
{
return(m_picbox);
}
}
|
|
|
Back to top |
|
|
Chris Miller
Joined: 27 Mar 2004 Posts: 514 Location: The Internet
|
Posted: Sat Dec 22, 2007 8:01 am Post subject: Re: DCs |
|
|
The *Graphics classes are DC wrappers. You are holding on to them yourself. Perhaps you should hold on to images and paint them instead. |
|
Back to top |
|
|
jvr
Joined: 19 Nov 2007 Posts: 10
|
Posted: Sat Dec 22, 2007 10:10 am Post subject: Re: DCs |
|
|
Never mind, I've changed the SkinButton class to avoid problems and now "standard" buttons are used automatically if the o. system is Win9x/ME. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|