Stoppt die Vorratsdatenspeicherung! Jetzt klicken && handeln!Willst du auch bei der Aktion teilnehmen? Hier findest du alle relevanten Infos und Materialien:
 
Regions und Skinning - Teil 2
von Plapperkatze am 4.Februar 2006 um 19:32
zurück zur Kategorie "Tutorials"

Heute machen wir sowas hier, ein bewegliches und teiltransparentes Fenster, erstellt aus einem Bitmap mit einer transparenten Farbe:



Dass das Mädchen Löcher im Kleid hat, liegt an dem Bitmap: Die Farbe Weiß wird nicht mitgezeichnet, und da das Kleid stellenweise so weiß ist wie der Hintergrund, werden auch diese Pixel weggelassen. Ihr schafft es sicher besser.

Wir benötigen also eine Region, die uns die Funktion HRGN ScanRegion(HBITMAP pBitmap, BYTE jTranspR, BYTE jTranspG, BYTE jTranspB) zurückgibt. Um diese Region zu erzeugen, benötigt sie allerdings die RGB Werte des Bitmaps, worauf man unter Windows nicht ohne Umwege zugreifen kann. Das erledigt die Funktion BYTE* Get24BitPixels(HBITMAP pBitmap, WORD *pwWidth, WORD *pwHeight), die einen Zeiger auf ein erzeugtes char-array zurückliefert.

Die beiden Funktionen stammen aus einem Flipcode-Tutorial von Vander Nunes (danke!), und sind so universell einsetzbar, dass ich sie einfach übernommen habe. Allerdings habe ich sie nicht nach C konvertiert, eure Quelldatei muss also *.cpp heissen, damit bcc32 sie richtig übersetzt.

Die Region zu erzeugen dauert eine ganze Weile, es ist also ratsam, diese als Ressource einzubinden, nachdem man sie einmal erstellt hat. Hier wird sie bei Programmstart erzeugt, was einige Sekunden in Anspruch nimmt.

Ich habe den HiRes-Timer (siehe: http://katze.dead-men.de/index.php?tutorial=33 ) zur allgemeinen Verwirrung mit eingebunden, er erfasst die Zeit, die die Erzeugung der Region benötigt.

#include <windows.h>
#include <stdio.h> // für sprintf

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
const char szAppName[]    = "Region Demo";

int width=640;
int height=480;

HBITMAP hBmp;

 RECT r;
 char c[256];

 LONGLONG Frequency, CurrentTime, LastTime;
 double TimeElapsed, TimeScale;
 BOOL CounterAvailable=FALSE;

int WINAPI WinMain(  HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
  MSG        msg;
  HWND       hWnd;

  WNDCLASS   wc;
 
  wc.style               = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc         = WndProc;
  wc.cbClsExtra          = 0;
  wc.cbWndExtra          = 0;
  wc.hInstance           = hInstance;
  wc.hCursor             = LoadCursor(NULL, IDC_ARROW);
  wc.hIcon               = LoadIcon(NULL, MAKEINTRESOURCE("1"));
  wc.hbrBackground       = (HBRUSH) GetStockObject(WHITE_BRUSH);
  wc.lpszClassName       = szAppName;
  wc.lpszMenuName        = NULL;

  RegisterClass(&wc);
 
  hWnd = CreateWindow(   szAppName,
                         szAppName,
                         WS_POPUP,
                         CW_USEDEFAULT,
                         CW_USEDEFAULT,
                         370,346,
                         NULL,
                         NULL,
                         hInstance,
                         NULL);

  ShowWindow(hWnd, iCmdShow);
  UpdateWindow(hWnd);
 
  while (GetMessage(&msg, NULL, 0, 0))
  {
     TranslateMessage(&msg);
     DispatchMessage(&msg);
  }
  return msg.wParam;
}

// Get24BitPixels gibt ein array mit RGB-Werten eines Bitmaps zurück (thx Vander Nunes)

BYTE* Get24BitPixels(HBITMAP pBitmap, WORD *pwWidth, WORD *pwHeight)
{
 BITMAP bmpBmp;
 LPBITMAPINFO pbmiInfo;
 BITMAPINFO bmiInfo;
 WORD wBmpWidth, wBmpHeight;

 GetObject(pBitmap, sizeof(bmpBmp),&bmpBmp);
 pbmiInfo   = (LPBITMAPINFO)&bmpBmp;

 wBmpWidth  = (WORD)pbmiInfo->bmiHeader.biWidth;
 wBmpWidth -= (wBmpWidth%4);                    
 wBmpHeight = (WORD)pbmiInfo->bmiHeader.biHeight;

 *pwWidth  = wBmpWidth;
 *pwHeight = wBmpHeight;

 BYTE *pPixels = new BYTE[wBmpWidth*wBmpHeight*3];
 if (!pPixels) return NULL;

 HDC hDC = GetWindowDC(NULL);

 bmiInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 bmiInfo.bmiHeader.biWidth = wBmpWidth;
 bmiInfo.bmiHeader.biHeight = -wBmpHeight;
 bmiInfo.bmiHeader.biPlanes = 1;
 bmiInfo.bmiHeader.biBitCount = 24;
 bmiInfo.bmiHeader.biCompression = BI_RGB;
 bmiInfo.bmiHeader.biSizeImage = wBmpWidth*wBmpHeight*3;
 bmiInfo.bmiHeader.biXPelsPerMeter = 0;
 bmiInfo.bmiHeader.biYPelsPerMeter = 0;
 bmiInfo.bmiHeader.biClrUsed = 0;
 bmiInfo.bmiHeader.biClrImportant = 0;

 int iRes = GetDIBits(hDC,pBitmap,0,wBmpHeight,(LPVOID)pPixels  ,&bmiInfo,DIB_RGB_COLORS);

 ReleaseDC(NULL,hDC);

 if (!iRes)
 {
   delete pPixels;
   return NULL;
 };
 return pPixels;
}

// Scan Region erzeugt eine Region aus dem Bitmap mit einer transparenten Farbe (thx Vander Nunes)

HRGN ScanRegion(HBITMAP pBitmap, BYTE jTranspR, BYTE jTranspG, BYTE jTranspB)
{
 WORD wBmpWidth,wBmpHeight;
 HRGN hRgn, hTmpRgn;
 BYTE *pPixels = Get24BitPixels(pBitmap, &wBmpWidth, &wBmpHeight);
 if (!pPixels) return NULL;

 hRgn = CreateRectRgn(0,0,wBmpWidth,wBmpHeight);
 if (!hRgn) { delete pPixels; return NULL; }

 DWORD p=0;
 for (WORD y=0; y<wBmpHeight; y++)
 {
   for (WORD x=0; x<wBmpWidth; x++)
   {
     BYTE jRed   = pPixels[p+2];
     BYTE jGreen = pPixels[p+1];
     BYTE jBlue  = pPixels[p+0];

     if (jRed == jTranspR && jGreen == jTranspG && jBlue == jTranspB)
     {
       hTmpRgn = CreateRectRgn(x,y,x+1,y+1);
       CombineRgn(hRgn, hRgn, hTmpRgn, RGN_XOR);
       DeleteObject(hTmpRgn);
     }
     p+=3;
   }
 }
 delete pPixels;
 return hRgn;
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

 PAINTSTRUCT ps;
 HDC hDC,hDC2;
 int x,y;

 HRGN hRegion1;

 switch (message)
 {
    case WM_CREATE:
    {
      GetClientRect(hWnd,&r);

      if (QueryPerformanceFrequency((LARGE_INTEGER*)&Frequency))
      {
        CounterAvailable = TRUE;
        TimeScale = 1.0/Frequency;
        QueryPerformanceCounter((LARGE_INTEGER*)&LastTime);
      }
      else
      {
        LastTime = timeGetTime();
        TimeScale = 0.001;
      }

      // bitmap laden
      hBmp=(HBITMAP)LoadImage(NULL,"matsu.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

      hRegion1 = ScanRegion(hBmp,255,255,255);
      SetWindowRgn(hWnd,hRegion1,TRUE);
      DeleteObject(hRegion1);
      if (CounterAvailable)QueryPerformanceCounter((LARGE_INTEGER*) &CurrentTime);
      else CurrentTime = timeGetTime();
      TimeElapsed = (CurrentTime - LastTime) * TimeScale;
      LastTime = CurrentTime;

      sprintf(c,"%lf",TimeElapsed);
      SetWindowText(hWnd,c);
    }
    break;
    case WM_PAINT:
    {
      hDC = BeginPaint(hWnd, &ps);
      hDC2 = CreateCompatibleDC(hDC);
      SelectObject(hDC2,hBmp);
      BitBlt(hDC,0,0,370,346,hDC2,0,0,SRCCOPY);
      DeleteDC(hDC2);
      EndPaint(hWnd, &ps);

      return 0;
    }
    case WM_LBUTTONDOWN:
    {
      SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION,NULL);
      break;
    }
    case WM_RBUTTONDOWN:
    case WM_DESTROY:
    {
       PostQuitMessage(0);
       return 0;
    }
 }
 return DefWindowProc(hWnd, message, wParam, lParam);
}

hier ist der download zu source und exe:
http://katze.dead-men.de/upload/13_regions.rar

hier das flipcode-Tutorial (englisch):
http://www.flipcode.com/articles/article_win32skins.shtml

gruesse, die plapperkatz

zurück zur Kategorie "Tutorials"
[0 Kommentare]

Name


Kommentar




Bitte abtippen


 
(C) 2006-20012 Plapperkatze - 215314 Besucher seit dem 23.01.2012 Login