bonjour à tous et à toutes,
voila j'ai créé un petit logiciel qui permet d'appliquer un effet de transparence sur une fenetre via une couleur de transparence.
Néanmoins ça ne fonctionne pas et ayant tout essayé je poste mon code source ici avec espoir...
Premiere fonction qui va permettre de transformer la fenetre en HBITMAP >>
HBITMAP HwndToBmpFile(HWND hwnd)
{
HDC memdc, hdc;
HANDLE hfl;
DWORD dwBytes, dwNumColors;
void *pBits;
HBITMAP hbmp;
BITMAPFILEHEADER fileheader;
RGBQUAD colors[256];
BITMAPINFO bmpinfo;
HGDIOBJ hret;
RECT rct;
hdc = GetWindowDC(hwnd);
if(!hdc) return 0;
GetWindowRect(hwnd, &rct);
rct.bottom -= rct.top;
rct.right -= rct.left;
rct.top = GetDeviceCaps(hdc, BITSPIXEL);
if(rct.top <= 8) dwNumColors = 256;
else dwNumColors = 0;
if(!(memdc = CreateCompatibleDC(hdc))) goto relHwndDc;
bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpinfo.bmiHeader.biWidth = rct.right;
bmpinfo.bmiHeader.biHeight = rct.bottom;
bmpinfo.bmiHeader.biPlanes = 1;
bmpinfo.bmiHeader.biBitCount = (WORD) rct.top;
bmpinfo.bmiHeader.biCompression = BI_RGB;
bmpinfo.bmiHeader.biSizeImage = 0;
bmpinfo.bmiHeader.biXPelsPerMeter = 0;
bmpinfo.bmiHeader.biYPelsPerMeter = 0;
bmpinfo.bmiHeader.biClrUsed = dwNumColors;
bmpinfo.bmiHeader.biClrImportant = dwNumColors;
hbmp = CreateDIBSection(hdc, &bmpinfo, DIB_PAL_COLORS, &pBits, NULL, 0);
if(!hbmp) goto errato;
hret = SelectObject(memdc, hbmp);
if(!hret || (hret == HGDI_ERROR)) goto errato;
if(!BitBlt(memdc, 0, 0, rct.right, rct.bottom, hdc, 0, 0, SRCCOPY)) goto errato;
if(dwNumColors) dwNumColors = GetDIBColorTable(memdc, 0, dwNumColors, colors);
fileheader.bfType = 0x4D42;
rct.left = dwNumColors * sizeof(RGBQUAD);
fileheader.bfSize = ((rct.right * rct.bottom * rct.top) >> 3) + rct.left + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
fileheader.bfReserved1 = fileheader.bfReserved2 = 0;
fileheader.bfOffBits = rct.left + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpinfo.bmiHeader.biClrImportant = 0;
bmpinfo.bmiHeader.biClrUsed = dwNumColors;
hfl = CreateFile(TEXT("c:\\monfichier.bmp"),GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if(hfl == INVALID_HANDLE_VALUE) { goto errato;}
WriteFile(hfl, &fileheader, sizeof(BITMAPFILEHEADER), &dwBytes, 0);
WriteFile(hfl, &bmpinfo.bmiHeader, sizeof(BITMAPINFOHEADER), &dwBytes, 0);
if(!dwNumColors) WriteFile(hfl, colors, rct.left, &dwBytes, 0);
WriteFile(hfl, pBits, (rct.right * rct.bottom * rct.top) >> 3, &dwBytes, 0);
CloseHandle(hfl);
DeleteDC(memdc);
errato:
DeleteDC(memdc);
relHwndDc:
ReleaseDC(hwnd, hdc);
return hbmp;
}
Seconde fonction qui va creer grâce aux regions un effet de transparence >>
HRGN BmpToRgn (HBITMAP hBmp, COLORREF cTransparentColor)
{
#define ALLOC_UNIT 100
HRGN hRgn = NULL;
if (!hBmp) return 0; // si bitmap invalide retourne
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm); // met les infos d'en tete du bitmap dans bm
UINT siz=bm.bmWidth*bm.bmHeight*4; // enregistre la taille des donnes de l'image
char *lpBmpBits=(char*)LocalAlloc(LMEM_FIXED,siz); // fait de la place pour les bits du bitmap
GetBitmapBits(hBmp,siz,lpBmpBits); // obtient les bits de l'image dans l'espace qu'on a reservé
bm.bmBits=lpBmpBits; // complete la strucutre bm avec les bits
while (bm.bmWidthBytes % 4) bm.bmWidthBytes++; // bmWidthBytes doit être divisible par 4
DWORD maxRects = ALLOC_UNIT;
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
pData->rdh.dwSize = sizeof(RGNDATAHEADER);
pData->rdh.iType = RDH_RECTANGLES;
pData->rdh.nCount = pData->rdh.nRgnSize = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
BYTE *p32 = (BYTE *)bm.bmBits;
for (int y = 0; y < bm.bmHeight; y++) // parcourt toutes les lignes de l'image, de haut en bas
{
for (int x = 0; x < bm.bmWidth; x++) // parcourt tous les pixels de la ligne, de gauche à droite
{
// Recherche une suite continue de pixels non transparents
int x0 = x;
long *p = (long *)(p32 + 4*x);
while (x < bm.bmWidth)
{
if ((unsigned)*p==cTransparentColor)
break; // ce pixel est transparent
p++;
x++;
}
if (x > x0)
{
// ajoute les pixels (de (x0, y) à (x, y+1)) à la region en tant que rectangle
if (pData->rdh.nCount >= maxRects)
{
GlobalUnlock(hData);
maxRects += ALLOC_UNIT;
hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) +
(sizeof(RECT) * maxRects), GMEM_MOVEABLE);
pData = (RGNDATA *)GlobalLock(hData);
}
RECT *pr = (RECT *)&pData->Buffer;
SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
if (x0 < pData->rdh.rcBound.left)
pData->rdh.rcBound.left = x0;
if (y < pData->rdh.rcBound.top)
pData->rdh.rcBound.top = y;
if (x > pData->rdh.rcBound.right)
pData->rdh.rcBound.right = x;
if (y+1 > pData->rdh.rcBound.bottom)
pData->rdh.rcBound.bottom = y+1;
pData->rdh.nCount++;
// Il parait que sous Windows 98, ExtCreateRegion() ne marche pas s'il y a trop de rectangles
// Pas de panique: on construit la region en deux fois
if (pData->rdh.nCount == 2000)
{
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
hRgn = h;
pData->rdh.nCount = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
}
}
}
// On passe à la ligne suivante
p32 += bm.bmWidthBytes;
}
// On cree la region
// (et, s'il y avait plus de 2000 rectangles, on la combine avec celle créee precedemment)
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else hRgn = h;
LocalFree((HLOCAL)lpBmpBits);
return hRgn;
}
La façon dont j'associe ces 2 fonctions >>
HRGN Rgn = BmpToRgn(HwndToBmpFile(fenetre), RGB(49,239,25));
SetWindowRgn(ghFGirl, Rgn, 1);
DeleteObject(Rgn);
merci bcp
@+