Newsgroup: it.comp.lang.c++
Titolo: HELP

devo realizzare delle 'pictures' senza contorrno da usare in un programma
WINDOWS (vale a dire dei disegni con il contorno trasparente come i files
.cur).
Ho fatto vari tentativi con i pochi programmi di grafica di cui dispongo
(paintbrush, capture della creativesoftworx, e photoimpact della unlead) e
l'unico tentativo che mi è riusciscito lo ho ottenuto con "resource
workshop" del compilatore Borland V 4.52. Ma anche in questo caso il sistema
spartano di costruzione del disegno, punto per punto, non rende utilizzabile
il risultato, che dovrebbe essere più sofisticato (acquisizione del disegno
tramite scanner).
Non sono esperto di grafica, e non sono interessato a diventarlo, il mio
scopo è solo quello di risolvere questo contingente problema.
Qualcuno potrebbe darmi un aiuto?
Angelo Moreschini
E-MAIL 
mran...@dedalus.it

...

Ciao Angelo,
potevi anche chiedermelo direttamente :-)
Cmq ti rispondo qui perche' il codice potrebbe essere utile a qualcun'altro
:-)
Anche se avresti dovuto chiedere a it.comp.programmare.win32 :-)
Qui siamo OT :-)
Ti posto una funzioncina che permette di assegnare al volo un colore di
background per una bmp.
Per avere un buon risultato, pero', dovresti fare in modo che il colore di
bkg sia diverso da tutti gli altri e lasciare il primo pixel col colore di
bkg (ma potresti anche scegliere un'altra strada).
Ciao
Nazzareno
P.S. L'ultima volta che ho postato, forse il cut&paste o il mal...tto OE, al
posto di parentesi graffe di chiusura erano venuti fuori dei newline.
Purtroppo, me ne sono accorto solo dopo averlo spedito :-(
Chiedo scusa al NG, sperando che non si verifichi di nuovo :-)
// -------------------------------------------------------------------------
#define ROP_ZERO_BRUSH 0x00E20746L
void chgBkColor(HBITMAP hbmp, COLORREF toColor)
{
  HDC hdcTmp = ::CreateCompatibleDC(0);
  BITMAP bmp;
  GetObject(hbmp, sizeof(BITMAP), &bmp);
  ::SelectObject(hdcTmp, (HGDIOBJ)hbmp);
  // presuppone che il colore di sfondo coincida con il primo pixel
  // in alto a sx
  COLORREF fromColor = ::GetPixel(hdcTmp, 0, 0);
  HDC hdcMask = ::CreateCompatibleDC(hdcTmp);
  // crea un bitmap monocromatico
HBITMAP hbmpMask = ::CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1 ,1 ,0);
  ::SelectObject(hdcMask, (HGDIOBJ)hbmpMask);
  // setta il colore di sfondo nel dc sorgente a quello scelto sopra
  COLORREF oldCol = ::SetBkColor(hdcTmp, fromColor);
  // ora nel dc monocromatico avremo a zero tutti i pixel corrispondenti
  // allo sfondo e a uno gli altri
  ::BitBlt(hdcMask, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcTmp, 0, 0, SRCCOPY);
  ::SetBkColor(hdcTmp, oldCol);
  HBRUSH brush = ::CreateSolidBrush(toColor);
  ::SelectObject(hdcTmp, (HGDIOBJ)brush);
  // con questo tipo di ROP quando il pixel del sorgente e' uno, lascia
  // intatto il destinazione, quando e' zero usa il colore del brush
  ::BitBlt(hdcTmp, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMask, 0, 0,
ROP_ZERO_BRUSH);
  ::DeleteObject(brush);
  ::DeleteObject(hbmpMask);
  ::DeleteDC(hdcMask);
  ::DeleteDC(hdcTmp);
}
// -----------------------------------------------------------------

  // intatto il destinazione, quando e' zero usa il colore del brush
E' il contrario, in entrambi i commenti :-)
Per farmi perdonare posto un'altra funzioncina che permette di avere il
bitmap con lo sfondo trasparente rispetto ad un altro bitmap. Se non
sbaglio, questo dovrebbe essere piu' rispondente alla richiesta fatta.
Naturalmente, il bitmap di bkg puo' essere prelevato dallo schermo e,
dovrebbe avere almeno le dimensioni di quello di foreground.
Ciao
Nazzareno
P.S. Scusate se continuo ad essere OT :-)
// -----------------------------------------------------------
static HDC createMask(HDC src, HBITMAP hbmp, int width, int height)
{
  ::SelectObject(src, (HGDIOBJ)hbmp);
  HDC hdcMask = ::CreateCompatibleDC(src);
 HBITMAP hbmpMask = ::CreateBitmap(width, height, 1 ,1 ,0);
  ::SelectObject(hdcMask, (HGDIOBJ)hbmpMask);
  COLORREF fromColor = ::GetPixel(src, 0, 0);
  COLORREF oldCol = ::SetBkColor(src, fromColor);
  ::BitBlt(hdcMask, 0, 0, width, height, src, 0, 0, SRCCOPY);
  ::SetBkColor(src, oldCol);
  ::DeleteObject(hbmpMask);
  return hdcMask;
}
// -----------------------------------------------------------
static void invertMask(HDC mask, int width, int height)
{
  ::BitBlt(mask, 0, 0, width, height, mask, 0, 0, DSTINVERT);
}
// -----------------------------------------------------------
static void doMaskHDC(HDC hdcTmp, HBITMAP hbmp, HDC hdcMask, int width, int
height)
{
  ::SelectObject(hdcTmp, (HGDIOBJ)hbmp);
  ::BitBlt(hdcTmp, 0, 0, width, height, hdcMask, 0, 0, SRCAND);
}
// -----------------------------------------------------------
static void makeFinalHDC(HDC dest, HDC bkg, int width, int height)
{
  ::BitBlt(hdcDest, 0, 0, width, height, hdcBkg, 0, 0, SRCPAINT);
}
// -----------------------------------------------------------
void chgBkgBmp(HBITMAP hbmpFrg, HBITMAP hbmpBkg)
{
  BITMAP bmp;
  GetObject(hbmpFrg, sizeof(BITMAP), &bmp);
  HDC hdcDest = ::CreateCompatibleDC(0);
  HDC mask = createMask(hdcDest, hbmpFrg, bmp.bmWidth, bmp.bmHeight);
 HDC hdcBkg = ::CreateCompatibleDC(0);
  doMaskHDC(hdcBkg, hbmpBkg, mask, bmp.bmWidth, bmp.bmHeight);
  invertMask(mask, bmp.bmWidth, bmp.bmHeight);
 doMaskHDC(hdcDest, hbmpFrg, mask, bmp.bmWidth, bmp.bmHeight);
 makeFinalHDC(hdcDest, hdcBkg, bmp.bmWidth, bmp.bmHeight);
  ::DeleteDC(mask);
  ::DeleteDC(hdcDest);
  ::DeleteDC(hdcBkg);
}
// -----------------------------------------------------------
// -----------------------------------------------------------