Friday, March 28, 2008

Que tal uma sintaxe em Portugues?


IMPORTANTE: O conteúdo deste post é sempre atualizado para a última versão do CajuScript.


Exemplo de uma sintaxe em Português usando o CajuScript.

Faça o download do CajuScript.

Na mesma pasta em que esta o jar do CajuScript crie o arquivo "carregaSintaxePortugues.cj", com o seguinte conteúdo:

[CODE]
$java.util.regex

syntaxPT = org.cajuscript.Syntax()
syntaxPT.setIf(Pattern.compile("^[\\s+s|s]e\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setElseIf(Pattern.compile("^[\\s+o|o]u\s+se\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setElse(Pattern.compile("^[\\s+o|o]u\\s+senao\\s+fa[z\\s+|z]$"))
syntaxPT.setIfEnd(Pattern.compile("^[\\s+f|f]i[m\\s+|m]$"))
syntaxPT.setLoop(Pattern.compile("^[\\s+e|e]nquanto\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setLoopEnd(Pattern.compile("^[\\s+f|f]i[m\\s+|m]$"))
syntaxPT.setTry(Pattern.compile("^[\\s+t|t]enta\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setTryCatch(Pattern.compile("^[\\s+p|p]ega\\s+o\\s+err[o\\s+|o]$"))
syntaxPT.setTryFinally(Pattern.compile("^[\\s+f|f]inalment[e\\s+|e]$"))
syntaxPT.setTryEnd(Pattern.compile("^[\\s+f|f]i[m\\s+|m]$"))
syntaxPT.setFunction(Pattern.compile("^[\\s+f|f]uncao\\s*([\\s+|[\\s*\\(]].+)\\s*faz"))
syntaxPT.setFunctionEnd(Pattern.compile("^[\\s+f|f]i[m\\s+|m]$"))
syntaxPT.setNull(Pattern.compile("nulo"))
syntaxPT.setReturn(Pattern.compile("retorna"))
syntaxPT.setImport(Pattern.compile("importa\\s+"))
syntaxPT.setRootContext(Pattern.compile("raiz\\."))
syntaxPT.setContinue(Pattern.compile("continua"))
syntaxPT.setBreak(Pattern.compile("para"))
syntaxPT.setOperatorOr(Pattern.compile("[\\s+|)\\s*]ou[\\s+|(\\s*]"))
syntaxPT.setOperatorAnd(Pattern.compile("[\\s+|)\\s*]e[\\s+|(\\s*]"))

org.cajuscript.CajuScript.addGlobalSyntax("PT", syntaxPT)

$"exemploSintaxePortugues.cj"
[/CODE]

E também o arquivo "exemploSintaxePortugues.cj", com o seguinte conteúdo:

[CODE]
caju.syntax: PT

importa java.lang

// IF = SE
x = 10
se x < 10 e x > 0 faz
System.out.println("X menor que 10!")
ou se x > 10 e x ! 10 faz
System.out.println("X maior que 10!")
ou se x = 10 ou x ! 0 faz
System.out.println("X igual 10!")
ou senao faz
System.out.println("X menor que 1!")
fim

// LOOP = ENQUANTO
x = 0
enquanto x < 100 e x >= 0 faz
System.out.println(x)
x += 1
se x = 10 faz
para
ou senao faz
continua
fim
fim

// FUNCTION = FUNCAO
x = 5
funcao addWithX(v1, v2) faz
retorna raiz.x + v1 + v2
fim
x = addWithX(10, 20)
System.out.println("X = "+ x)

// TRY/CATCH = TENTA/PEGA
tenta e faz
"".substring(0, -1)
pega o erro
System.out.println("Erro: "+ e.getMessage())
finalmente
System.out.println("Finalmente...")
fim

System.out.println("\n\nSyntax em portugues executada com sucesso!\n")

Thread.sleep(10000)
[/CODE]

Agora é só executar com o comando:

[CODE]
java -jar cajuscript.jar carregaSintaxePortugues.cj
[/CODE]

Pronto! :P

Não convêm usar acentos na sintaxe, por que pode dar alguns problemas de encoding ao transportar o arquivo por vários sistemas operacionais, como do linux para o windows. Mas quem não arrisca não petisca.

Toda sugestão é bem vinda.

Saturday, February 23, 2008

Apache 2.2 - Modules

No Apache 2.2 resolveram mudar os nomes dos modulos, o que tem dado alguma dor de cabeça...

Lista da mudanças nos nomes dos modulos.

Se tiver o seguinte erro:

[CODE]

Starting httpd: httpd: Syntax error on line 170 of /etc/httpd/conf/httpd.conf: Cannot load /etc/httpd/modules/mod_access.so into server: /etc/httpd/modules/mod_access.so: cannot open shared object file: No such file or directory

[/CODE]

Segue a lista dos modulos corrigido:

[CODE]
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authn_anon_module modules/mod_authn_anon.so
LoadModule authn_dbm_module modules/mod_authn_dbm.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule ldap_module modules/mod_ldap.so
LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
LoadModule include_module modules/mod_include.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule mime_magic_module modules/mod_mime_magic.so
LoadModule cern_meta_module modules/mod_cern_meta.so
LoadModule expires_module modules/mod_expires.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule headers_module modules/mod_headers.so
LoadModule usertrack_module modules/mod_usertrack.so
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule asis_module modules/mod_asis.so
LoadModule info_module modules/mod_info.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule imagemap_module modules/mod_imagemap.so
LoadModule actions_module modules/mod_actions.so
LoadModule speling_module modules/mod_speling.so
LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule cache_module modules/mod_cache.so
LoadModule suexec_module modules/mod_suexec.so
LoadModule disk_cache_module modules/mod_disk_cache.so
LoadModule file_cache_module modules/mod_file_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so
LoadModule cgi_module modules/mod_cgi.so
[/CODE]

Fiz isto no CentOS 5.1, mas deve ajudar na configuração em outras distribuições.

Wednesday, February 13, 2008

Anaconda? Sucuri? Ou história de pescador?

Acho que toda gente já deve ter recebido algum e-mail falando sobre esta cobrinha:

E acompanha um texto do gênero:

[CODE]

Anaconda...
Sucuri em Barra do Piraí - RJ
VEJAM SÓ O TAMANHO DA
"BOQUINHA" DA CRIANÇA.


Acreditem, esta sucuri morreu eletrocutada na cerca elétrica
que separa a empresa Thyssen, em Barra do Piraí - RJ, de uma
fazenda vizinha.
O acontecimento parou a fábrica, e o dia inteiro
foi o maior entra e sai de biólogos do Rio e São Paulo,
para analisarem a cena que se tornou motivo de
preocupação para todos.

Será preciso rever conceitos sobre acampar e passar a noite às
margens de represa pescando.
Reparem no formato de sua barriga, que ela estava bem alimentada.
Segundo a turma da segurança da Thyssen e o pessoal da prefeitura
de Barra do Piraí, os órgãos responsáveis estão assustados,
pois este animal, segundo os especialistas, só vive na Amazônia e Pantanal.
É, os especialistas também se enganam.

[/CODE]

Como já tinha recebebido vários e-mails com estas imagens, e desta vez me chamou a atenção no título dizer "Anaconda" e no texto dizer "Sucuri", eu pensava que Anaconda e Sucuri fossem espécies diferentes, mas o wikipedia diz que Sucuri é uma espécie de Anaconda:
http://pt.wikipedia.org/wiki/Anaconda

Ok, boa, aprendi qualquer coisa, agora e o resto?

Joguei no Google: "sucuri morreu eletrocutada" e também "anaconda morreu eletrocutada"...

Aparece varios links, e comecei a ver o que diziam:

...cerca elétrica que separa a
empresa Thyssen, em Barra do Piraí - RJ...

Há foi daqui que o e-mail veio. -.-

...Fábrica da Votorantim em Resende (RJ), de uma fazenda vizinha próxima ao Rio Paraíba do Sul...
Opa afinal foi em Resende no Rio de Janeiro, só que na fábrica Votorantim! -.^

...Siderúrgica Thyssen, de Barra do Piraí (PR)...
Não não, foi na Siderúrgica Thyssen e foi na barra do Piraí mesmo... só que fica no Pará!?!?! o.O

E eu garanto que estas fotos foram tiradas lá me casa, num domingo de manhã quando faltou a luz fui no quintal e vi lá a cobra na cerca elétrica, tinha acabado de comer o meu cão, o problema é saber como ela conseguio entrar e depois não conseguio sair, e coitadinho do meu cão Fubá... :P

Mais um daqueles e-mails com informação bem informativa! As fotos impressionam, mas o texto... vai na volta até foi na Bolívia ou EUA...

Apagão mundial a 29 Fev 08 (PELO NOSSO PLANETA) ???

Recebi um e-mail bem engraçado dizendo o seguinte:

[CODE]
Apagão mundial a 29 Fev 08 (PELO NOSSO PLANETA)
Apagão mundial: No dia 29 de Fevereiro de 2008 das 19:55 às 20:00 horas
propõe-se apagar todas as luzes e se possível todos os aparelhos
eléctricos, para o nosso planeta poder 'respirar'.

MARCAR NA AGENDA!!!!!

Se a resposta for massiva, a poupança energética pode ser brutal.
Só 5 minutos, para ver o que acontece.
Sim, estaremos 5 minutos às escuras, podemos acender uma vela e
simplesmente ficar a olhar para ela, estaremos a respirar nós e o
planeta.
Lembrem-se que a união faz a força e a Internet pode ter muito poder
e podemos mesmo fazer algo em grande.
Passa a notícia, se tiveres amigos a viver noutros países envia-lhes e
pede-lhes que façam a tradução e adaptem as horas.

[/CODE]

Claro que para averiguar a veracidade dos fatos fui jogar no Google e numa pesquisa rápida a única referência a isto que encontrei foi:
http://tresemdezembro.blogspot.com/2008/02/what-do-you-say.html

Não há link para uma notícia de um jornal sério por exemplo, e como é óbvio é mais uma daquelas coisas que alguém resolveu inventar.

Fiquei a pensar como isto não faz sentido, por exemplo, sempre que vou dormir tudo em casa fica desligado, logo faço um grande apagão lá em casa (afinal a conta da luz não é barata), se eu dormir 5 minutos a mais (como custumo fazer todos os dias e saio sempre atrasado) já estou colaborando com o planeta!

Agora vai ser lindo ver um bando de gente desligando tudo durante 5 minutos. E eu vou fazer o contrário, vou ligar tudo! Por isso em vez de desligar tudo no dia 29, vamos liguar tudo e vamos ver se a companhia elétrica aguenta :P

Mas pelo que parece houve uma iniciativa mundial com esta finalidade, mas em 1 de fevereiro de 2007. Como pode ser verificado aqui. Então parece que gostaram da idéia e resolveram organizar um evento destes todo ano, neste ano já vai com atraso...

Monday, January 14, 2008

Restaurar Base de Dados no SQLServer

Podia ser muito mais simples, mas para que facilitar se da para complicar? E para eu nunca esquecer como restaurar uma base de dados no SQLServer, resolvi fazer este post.

Quando se tenta pelas vias normais e da o erro:
Restore failed for Server...
E tenta por script e da outro erro:
Directory lookup for the file...
E se a base de dados esta em uso:
Exclusive access could not be obtained because the database is in use.

Então esta faltando é os comandos corretos...

Limpar as conexões ativas:

USE Master

ALTER DATABASE YOUR_DATABASE_NAME SET SINGLE_USER WITH ROLLBACK IMMEDIATE

GO

USE Master

ALTER DATABASE YOUR_DATABASE_NAME SET MULTI_USER WITH ROLLBACK IMMEDIATE

GO

Para poder ver o nome do Data e do Log, e ainda outros dados do backup, informações precisosas para o próximo passo:

RESTORE FILELISTONLY FROM DISK = 'C:\BACKUP.bak'

Agora é so fazer o restore assim:

RESTORE DATABASE NewDataBaseName FROM DISK = 'C:\BACKUP.bak'
WITH
MOVE 'BackupDatabase_Data' TO 'C:\MSSQL\Data\NewDataBaseName.mdf',
MOVE 'BackupDatabase_Log' TO 'C:\MSSQL\Data\NewDataBaseName.ldf'


Agora já sei aonde encontrar isto mais rápido da próxima vez :P

Sunday, January 13, 2008

NetBeans 6 vs OpenSuse 10.3

Se tiver problemas com OpenSuse 10.3 para rodar o NetBeans 6, o bug-buddy acusando um bug e parando a execução logo na inicialização. Então vou explicar como instalar o JDK 6 e o NetBeans 6 no OpenSuse 10.3 e resolver este problema.

Instalação JDK 6:
- Em java.sun.com abrir o link para o Java SE, depois fazer o download do JDK 6 Update 4 versão para Linux o que tem a extenção .rpm.bin:
jdk-6u4-linux-x64-rpm.bin
- Dar permissões de execução para o arquivo:
chmod +x jdk-6u4-linux-x64-rpm.bin
- Executar:
./jdk-6u4-linux-x64-rpm.bin
- Vai ser criado no mesmo diretório varios arquivos *.rpm, para instalar execute:
sudo /sbin/yast2 -i jdk-6u4-linux-amd64.rpm
- O JDK 6 será instalado em:
/usr/java/jdk1.6.0_04
- E também terá estes atalhos para o jdk:
/usr/java/latest
/usr/java/default

Instalação NetBeans 6:
- Em www.netbeans.org faça o download do NetBeans 6 versão Linux, eu usei a versão "All".
- Dar permissões de execução para o arquivo:
chmod +x netbeans-6.0-linux.sh
- Eu instalei em /opt, caso queira instalar ai também faça assim:
sudo mkdir /opt/netbeans-6.0
sudo chmod a+rwx /opt/netbeans-6.0
sudo mkdir /opt/glassfish-v2
sudo chmod a+rwx /opt/glassfish-v2
- Agora execute o arquivo de instalação do NetBeans 6, e escolha a pasta de instalação, se for no /opt/netbeans-6.0 escolha esta pasta e o GlassFish também /opt/glassfish-v2, e eu coloquei em JDK /usr/java/latest.
- Será criado atalhos no desktop e nos programas.
- Execute...

Caso de Error, do bug-buddy, como aconteceu no meu caso, ele pode ser removido, não vai fazer falta, para o remover execute:
sudo zypper rm bug-buddy

Agora é só executar outra vez e deverá ter o problema resolvido, e o NetBeans 6 a funcionar perfeitamente.

Friday, January 11, 2008

TextBoxRevolution

Precisei fazer uma TextBox com fundo transparente e também imagem de fundo, totalmente customizada, procurei na net e encontrei uma base, então resolvi melhorar e organizar bem o código, e esta ai o resultado.

Uma coisa que as vezes faz falta no Windows.Form, é o Attributes nos Controls, algo que temos no Asp.Net mas não no Windows.Form, e como eu também precisava deste recurso na TextBox então resolvi implementar isto também, por isso esta TextBox também suporta o Attributes, TextBoxRevolution.Attributes, assim já é possível anexar outros objetos ao Control.

[CODE]
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace TextBoxRevolutionTest
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form form = new Form();
form.Text = "TextBoxRevolution";
form.Width = 450;
form.Height = 250;
string text = @"
The Foundations of the GPL
Nobody should be restricted by the software they use. There are four freedoms that every user should have:
* the freedom to use the software for any purpose,
* the freedom to share the software with your friends and neighbors,
* the freedom to change the software to suit your needs, and
* the freedom to share the changes you make.
When a program offers users all of these freedoms, we call it free software.
Developers who write software can release it under the terms of the GNU GPL. When they do, it will be free software and stay free software, no matter who changes or distributes the program. We call this copyleft: the software is copyrighted, but instead of using those rights to restrict users like proprietary software does, we use them to ensure that every user has freedom.
";
TextBoxRevolution textBoxRevolution = new TextBoxRevolution();
textBoxRevolution.Name = "textBoxRevolution";
textBoxRevolution.Dock = DockStyle.Fill;
textBoxRevolution.Control.Name = "textBoxRevolutionOut";
textBoxRevolution.Transparent = true;
textBoxRevolution.Height = 0;
textBoxRevolution.TopMargin = 5;
textBoxRevolution.BorderStyle = BorderStyle.None;
textBoxRevolution.Multiline = true;
textBoxRevolution.ForeColor = Color.FromArgb(0, 0, 0);
textBoxRevolution.Text = text;
textBoxRevolution.Select(0, 0);
textBoxRevolution.Background += new TextBoxRevolution.OnBackground(textBoxRevolution_Background);
form.Controls.Add(textBoxRevolution);
Application.Run(form);
}
static Image textBoxRevolution_Background(TextBoxRevolution textBoxRevolution)
{
Color topColor = Color.FromArgb(235, 237, 241);
Color bottomColor = Color.FromArgb(225, 229, 232);
if (textBoxRevolution.Control.Name.EndsWith("Over"))
{
topColor = Color.FromArgb(249, 247, 255);
bottomColor = Color.FromArgb(238, 234, 255);
}
Bitmap img = new Bitmap(textBoxRevolution.Width, textBoxRevolution.Height);
Graphics g = Graphics.FromImage(img);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.FillRectangle(new SolidBrush(topColor), 0, 0, textBoxRevolution.Width, textBoxRevolution.Height);
g.FillRectangle(new SolidBrush(bottomColor), 0, textBoxRevolution.Height / 2, textBoxRevolution.Width - 50, textBoxRevolution.Height / 2);
g.FillEllipse(new SolidBrush(bottomColor), textBoxRevolution.Width - 100, textBoxRevolution.Height / 2, 100, 20);
g.FillRectangle(new SolidBrush(bottomColor), textBoxRevolution.Width - 50, (textBoxRevolution.Height / 2) + 10, textBoxRevolution.Width, textBoxRevolution.Height / 2);
return img;
}
}
}

namespace System.Windows.Forms
{
public class TextBoxRevolution : TextBox
{

public delegate Image OnBackground(TextBoxRevolution textBoxRevolution);
public event OnBackground Background;

PictureBox pictureBox = null;
Dictionary<string, object> attributes = new Dictionary<string, object>();

public TextBoxRevolution()
{
pictureBox = new PictureBox();
pictureBox.Dock = DockStyle.Fill;
this.ShortcutsEnabled = false;
this.Cursor = Cursors.Arrow;
this.Controls.Add(pictureBox);
}

public Dictionary<string, object> Attributes
{
get
{
return attributes;
}
set
{
attributes = value;
}
}

bool transparent = false;
public bool Transparent
{
get
{
return transparent;
}
set
{
transparent = value;
}
}

public PictureBox Control
{
get
{
return pictureBox;
}
}

int topMargin = 0;
public int TopMargin
{
get
{
return topMargin * -1;
}
set
{
topMargin = value;
}
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case Win32.WM_PAINT:
Draw();
break;
case Win32.WM_HSCROLL:

case Win32.WM_VSCROLL:
this.Invalidate();
break;
}
}

public void Draw()
{
Bitmap bmpCaptured = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
Bitmap bmpResult = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
Rectangle r = new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
Win32.CaptureWindow(this, ref bmpCaptured);
if (Transparent)
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
}
ImageAttributes imgAttrib = new ImageAttributes();

if (Transparent)
{
ColorMap[] colorMap = new ColorMap[1];
colorMap[0] = new ColorMap();
colorMap[0].OldColor = Color.White;
colorMap[0].NewColor = Color.Transparent;
imgAttrib.SetRemapTable(colorMap);
}
Graphics g = Graphics.FromImage(bmpResult);


try
{
g.DrawImage(Background(this), r, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, GraphicsUnit.Pixel, imgAttrib);
}
catch
{
}
g.DrawImage(bmpCaptured, r, 0, TopMargin, this.ClientRectangle.Width, this.ClientRectangle.Height, GraphicsUnit.Pixel, imgAttrib);
g.Dispose();
pictureBox.Image = (Image)bmpResult.Clone();
}

public int ContentHeight
{
get
{
return LinesCount * base.Font.Height;
}
}

public int LinesCount
{
get
{
const int EM_GETLINECOUNT = 186;
int lineCount = Win32.SendMessage(base.Handle, EM_GETLINECOUNT, IntPtr.Zero, IntPtr.Zero);
return lineCount + 1;
}
}
}

public class Win32
{
public const int WM_MOUSEMOVE = 0x0200;
public const int WM_LBUTTONDOWN = 0x0201;
public const int WM_LBUTTONUP = 0x0202;
public const int WM_RBUTTONDOWN = 0x0204;
public const int WM_LBUTTONDBLCLK = 0x0203;
public const int WM_MOUSELEAVE = 0x02A3;
public const int WM_PAINT = 0x000F;
public const int WM_ERASEBKGND = 0x0014;
public const int WM_PRINT = 0x0317;
public const int EN_HSCROLL = 0x0601;
public const int EN_VSCROLL = 0x0602;
public const int WM_HSCROLL = 0x0114;
public const int WM_VSCROLL = 0x0115;
public const int EM_GETSEL = 0x00B0;
public const int EM_LINEINDEX = 0x00BB;
public const int EM_LINEFROMCHAR = 0x00C9;
public const int EM_POSFROMCHAR = 0x00D6;
[DllImport("USER32.DLL", EntryPoint = "PostMessage")]
public static extern bool PostMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("USER32.DLL", EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("USER32.DLL", EntryPoint = "GetCaretBlinkTime")]
public static extern uint GetCaretBlinkTime();
public const int WM_PRINTCLIENT = 0x0318;
public const long PRF_CHECKVISIBLE = 0x00000001L;
public const long PRF_NONCLIENT = 0x00000002L;
public const long PRF_CLIENT = 0x00000004L;
public const long PRF_ERASEBKGND = 0x00000008L;
public const long PRF_CHILDREN = 0x00000010L;
public const long PRF_OWNED = 0x00000020L;
public static bool CaptureWindow(System.Windows.Forms.Control control, ref System.Drawing.Bitmap bitmap)
{
Graphics g2 = Graphics.FromImage(bitmap);
int meint = (int)(PRF_CLIENT | PRF_ERASEBKGND);
System.IntPtr meptr = new System.IntPtr(meint);
System.IntPtr hdc = g2.GetHdc();
Win32.SendMessage(control.Handle, Win32.WM_PRINT, hdc, meptr);
g2.ReleaseHdc(hdc);
g2.Dispose();
return true;
}
}
}
[/CODE]