Newsgroup: it.comp.programmare.win32
Titolo: HDC e TextBox

Ciao a tutti,
ho un'esigenza un po' particolare: dovrei trasformare il contenuto di
una textbox multiline in una rappresentazione bitmap (un jpeg alla fine
del processo).
Io pensavo di procedere cosi':
- Creo un buffer per i dati raw della bitmap
- Ricavo l'handle di finestra del textbox
- Ricavo l'hdc partendo dall'hwnd precedente
- Uso la GetPixel su tutti i pixel del HDC valorizzando man mano il buffer
- Creo infine una variabile di tipo BITMAP con i parametri di width
etc.. e assegno il buffer preparato precedentemente
A questo punto dovrei avere una rappresentazione bitmap del textbox, per
trasformarla in jpeg immagino di poter usare qualche libreria di sistema
ma non so quale e come, qualcuno ha suggerimenti?
Inoltre il modo per ricavare l'immagine mi pare macchinoso, esistomo
metodi piu' immediati?
Grazie
Fabrizio

 Io pensavo di procedere cosi':
No. Il modo corretto per fare quello che ti serve è:
CreateCompatibleDC: crei un device contex in memoria
CreateDIBitmap: crei un bitmap con le caratteristiche che ti servono
SelectObject: selezioni il bitmap nel device context (tieniti l'hbitmap
selezionato di default).
Disegni o, nel tuo caso, scrivi nel device context appena creato.
SelectObject: selezioni il bitmap che ti eri salvato (quello di default) nel
device context per "liberare" l'associazione tra il tuo hbitmap e il device
context (non chiedermi di più, perché non ho capito il perché: la Microsoft
però dice "Remarks: This function returns the previously selected object of
the specified type. An application should always replace a new object with
the original, default object after it has finished drawing with the new
object.")
DeleteObject: cancelli il bitmap e il device context.
Adesso nel puntatore in memoria che hai usato per creare il bitmap hai i 
pixel che ti servono. Ti serve solo una funzione per salvare in JPEG. O te 
la fai (ma te lo sconsiglio, per esperienza personale) o meglio usi una 
libreria. Facile da usare c'è la IJG, oppure so che nelle GDIPlus c'è già 
fatto.
-- 
/* Costantino Grana                                */
main(int c,char**o){char*s=c?"+L7?+;:7?+:OKIK+9?;9=;"
":+9?;:<:;+9?;;;:;+9<:;<::;+RLJ;K9+":1[o],t,a=!c,m;do
for (m=*s-'0',t=a?m/c:m%c;m>>7?c=1<<m+8,!a&&puts(&a)*
*&a:t--;printf("  \0/*"+a));while ((a^=3)||a[++s]);;}
/* Original code due to Chris Brown... impressive! */

Ti ringrazio per la risposta ma credo di essermi spiegato male.
Io ho il textbox multiline nel quale scrivo qualcosa (manualmente come
in qualsiasi textbox). Quello che voglio fare è trasformare il contenuto
 del textbox in un immagine. Immagina quello che viene fatto con gli
"screen capturer" ma confinato ad un textbox.
Quello che mi hai descritto mi pare il processo per scrivere (o
disegnare) nel textbox da codice.
Spero di non aver mal interpretato la risposta....
Grazie
Fabrizio


del processo).
Io uso le GDI+. Ti rispondo come ha fatto Costantino, cioe'
credendo che tu debba scrivere, mentre invece l'immagine l'hai
gia'. Questo e' un esempio di codice, non e' difficile adattarlo
alle tue esigenze:
#include <gdiplus.h>
using namespace Gdiplus;
{
Bitmap *bp;
Graphics *gp;
Font *fn;
SolidBrush *sb;
Color *cc;
PointF *pt;
HDC hdc;
WCHAR StrW [ ... ];
CLSID pClsid;
EncoderParameters encP;
UINT num = 0;          // number of image encoders
UINT size = 0;         // size of the image encoder
                               // array in bytes
UINT j;
ULONG quality;
int width = ... ;
int height = ... ;
bp = new Bitmap (width,height, ... );
// qui disegni il fondo della Bitmap, un bordo, etc.
bp->beginPaint ();
hdc = bp->getDC ();
// dalla HDC usi le funzioni GDI classiche,
// oppure:
gp = new Graphics (hdc);
fn = new Font ( ... , ... );
cc = new Color ( ... , ... , ... );
sb = new SolidBrush (*cc);
pt = new PointF ( ... , ... );
gp->SetTextRenderingHint (TextRenderingHintAntiAlias);
// prepari StrW
gp->DrawString (StrW,wcslen (StrW),fn,*pt,sb);
// oppure usi la DrawString che accetta come
// parametro il rettangolo dei contorni del testo,
// se deve essere scritto su piu' linee in una
// determinata posizione.
delete pt,sb,cc,fn,gp;
bp->endPaint ();
// qui il gioco si fa duro...
encP.Count = 1;
encP.Parameter[0].Type = EncoderParameterValueTypeLong;
encP.Parameter[0].NumberOfValues = 1;
GetImageEncodersSize (&num,&size);
pImageCodecInfo = (ImageCodecInfo*) (malloc (size));
GetImageEncoders (num,size,pImageCodecInfo);
for (j=0;j<num;++j)
   {
   if (wcscmp (pImageCodecInfo [j].MimeType,L"image/jpeg") == 0)
      {
      pClsid = pImageCodecInfo [j].Clsid;
      free (pImageCodecInfo);
      encP.Parameter[0].Guid = EncoderQuality;
      quality = ... ;   // qualita' di compressione da 0 a 100
      encP.Parameter[0].Value = &quality;
      bp->Save ( ... nome_file ... ,&pClsid,&encP)
      }
   }
delete bp;
}
Il codice non e' testato. Noterai che le GDI+ stampano lo stesso
font con dimensioni un po' diverse dalle GDI.

 Spero di non aver mal interpretato la risposta....
Hai capito bene. Ero io che non avevo molto chiara la cosa. Invece che fare 
uno screenshot, non va bene leggere il contenuto e fare una DrawText 
seguendo il metodo indicato?
Se non va bene, puoi però ottenere il device context della tua textbox e 
fare semplicemente BitBlt sull'immagine. Assicurati di creare un bitmap 
della dimensione giusta!


Grazie,
in realtà non sapevo che GDI+ fosse usabile anche in un progetto C++
"liscio" (l'ho usato spesso in .Net con C#).
In questi giorni non ho avuto modo di provare ma spero di riuscire nei
prossimi.
Un'ultima domanda: se invece di salvare su un file il jpeg volessi
metterne il contenuto in un buffer in memoria esiste un metodo veloce o
devo inventarmi qualcosa io (guardero' la documentazione ovviamente ma
giusto per avere un input). Se come su .Net immagino si possa usufruire
di stream di qualche tipo.....
grazie


di stream di qualche tipo.....
I programmo in C puro, quindi evito alcune caratteristiche che
rischiano di farmi inciampare... Comunque noterai il costruttore
della classe Image (e la sottoclasse Bitmap) che ricevono come
parametro un puntatore all'interfaccia IStream... ma con le COM
vado poco d'accordo.
Se ricambi il favore con un esempio te ne saro' grato!

Proprio per prendere due righe di esmepio ecco:
Response.ContentType = "image/png";
System.Drawing.Bitmap img = new System.Drawing.Bitmap(width, height);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(img);
g.FillRectangle(Brushes.White, 0, 0, width, height);
img.Save(Response.OutputStream ,
System.Drawing.Imaging.ImageFormat.Png);
Qui lavoro in un progetto web e creo dinamicamente un'immagine png, lo
stream usato (OutputStream ) corrisponde allo stream verso il browser.
