#include <windows.h>
#include <time.h>    // tu jest deklaracja funkcji time
#include <stdlib.h>

LRESULT CALLBACK ProceduraOkna (HWND, UINT, UINT, LONG); // deklaracja zapowiadająca

int odslona = -1; 

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE, 
                    LPSTR , int nCmdShow)		   
{
  const char nazwa_klasy_okien[] = "MojeOkno";

  WNDCLASSEX  wndclass = {0};
  wndclass.cbSize       	= sizeof(WNDCLASSEX);
  wndclass.style        	= CS_HREDRAW | CS_VREDRAW;  
  wndclass.lpfnWndProc  	= ProceduraOkna; 
  wndclass.hInstance    	= hInstance;                
  wndclass.hCursor      	= LoadCursor (NULL, IDC_ARROW);	
  wndclass.hIcon        	= LoadIcon   (NULL, IDI_APPLICATION); 
  wndclass.hbrBackground	= (HBRUSH) GetStockObject (WHITE_BRUSH);
  wndclass.lpszClassName	= nazwa_klasy_okien;
  wndclass.hIconSm      	= LoadIcon   (NULL, IDI_APPLICATION);
  
  srand(time(0));  // inicjacja generatora liczb pseudolosowych
  
  RegisterClassEx (&wndclass);	
  HWND hwnd = CreateWindowEx ( 0,
    nazwa_klasy_okien,
    "Pędzle i pióra",	
    WS_OVERLAPPEDWINDOW,			
    CW_USEDEFAULT, CW_USEDEFAULT, 
    CW_USEDEFAULT, CW_USEDEFAULT,
    0,
    0,
    hInstance,
    0);
  if (hwnd == 0)
    return -1;
  
  ShowWindow (hwnd, nCmdShow);			
  
  /* Pętla komunikatów: */
  int result;
  MSG msg;
  while ((result = GetMessage (&msg, NULL, 0, 0) ) != 0) 
  {
    if (result == -1) return -1;
    TranslateMessage (&msg);
    DispatchMessage (&msg);            
  }	                                   
  
  return msg.wParam;
}

// Generator liczb pseudolosowych z przedzialu 0..n-1
int Random(int n)
{
  return int(n*( rand()/double(RAND_MAX+1) ));
}

/***   PROCEDURA OKNA   ***/

LRESULT CALLBACK ProceduraOkna (HWND hwnd, UINT message,
                                UINT wParam, LONG lParam)
{
  switch(message)
  {
    case WM_PAINT:
    {
      PAINTSTRUCT ps;
      RECT        klient;

      ::odslona++;
 //     InvalidateRect(hwnd, &klient, true);
      
      HDC hdc = BeginPaint (hwnd, &ps);
      GetClientRect (hwnd, &klient);
      const int szer = klient.right - klient.left;
      const int wyso = klient.bottom - klient.top;
      
      for (int i=0; i < 100; i++, Sleep(0)) 
      {
        // tworzymy losowy pędzel 
        HBRUSH moj_pedzel;
        COLORREF kolor_pedzla = RGB( Random(256), Random(256), Random(256) );
        
        if (Random(2) == 0)
        {
          // tworzymy pędzel malujący pełnym ("solid"), losowo wybranym  kolorem
          moj_pedzel = CreateSolidBrush(kolor_pedzla);
        }
        else
        {
          // tworzymy pędzel malujący losowo wybrane wzorki "wzorki" ("hatch") w losowym kolorze
          int styl_pedzla;
          switch(Random(6))
          {
          case 0: styl_pedzla = HS_BDIAGONAL;  break;
          case 1: styl_pedzla = HS_CROSS;      break;
          case 2: styl_pedzla = HS_DIAGCROSS;  break;
          case 3: styl_pedzla = HS_FDIAGONAL;  break;
          case 4: styl_pedzla = HS_HORIZONTAL; break;
          case 5: styl_pedzla = HS_VERTICAL;   break;
          }
          moj_pedzel = CreateHatchBrush(styl_pedzla, kolor_pedzla);
        }
        
        // tworzymy pióro
        COLORREF kolor_piora =  RGB( Random(256), Random(256), Random(256) );
        
        int styl_piora;
        switch(Random(6)) // liczba losowa od 0 do 5
        {
          case 0: styl_piora = PS_SOLID;      break;
          case 1: styl_piora = PS_DASH;       break;
          case 2: styl_piora = PS_DOT;        break;
          case 3: styl_piora = PS_DASHDOT;    break;
          case 4: styl_piora = PS_DASHDOTDOT; break;
          case 5: styl_piora = PS_NULL;       break;
        }
        
        int szerokosc_piora = 1;
        if (styl_piora == PS_SOLID)
          szerokosc_piora = Random(10);
        HPEN moje_pioro = CreatePen(styl_piora, szerokosc_piora, kolor_piora);
        
        // wybieramy nasze pióro i pędzel
        HPEN stare_pioro = (HPEN)SelectObject(hdc, moje_pioro);
        HBRUSH stary_pedzel = (HBRUSH)SelectObject(hdc, moj_pedzel);
        
        // rysujemy
        const int x1 = Random(szer-10) - 20;
        const int y1 = Random(wyso-10) - 20;
        const int x2 = x1 + Random(130) + 20;
        const int y2 = y1 + Random(130) + 20;
        if(Random(2) == 0)
          Rectangle(hdc, x1, y1, x2, y2);
        else
          Ellipse(hdc, x1, y1, x2, y2);
        
        // z powrotem w kontekście urządzenia wybieramy stare pióro i pedzel 
        SelectObject(hdc, stary_pedzel);
        SelectObject(hdc, stare_pioro);
        
        // usuwamy nasze pioro i pedzel
        DeleteObject(moje_pioro);
        DeleteObject(moj_pedzel);   
      }  

      char* tytuly[] = {"polski", "grecki", "symbol", "hebrajski", "ANSI", "arabski"};
      const int charset_tab [] = {EASTEUROPE_CHARSET, GREEK_CHARSET, SYMBOL_CHARSET,
        HEBREW_CHARSET, ANSI_CHARSET, ARABIC_CHARSET };
      int charset = charset_tab[::odslona %6];

      char  bufor[256];
      wsprintf(bufor, "Pędzle, pióra i czcionka; kodowanie: \"%s\" (%d-a odsłona)", 
          tytuly[::odslona % 6], ::odslona);
      SetWindowText(hwnd, bufor);

      HFONT nowa_czcionka = CreateFont(
        -(30 + 2*Random(10)),
        0,
        Random(900) - 450,
        0,
        FW_NORMAL,
        0,
        0,
        0,
        charset,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY,
        FF_SCRIPT,
        0
      );

      HFONT stara_czcionka = (HFONT) SelectObject(hdc, nowa_czcionka);
      SetTextColor (hdc, RGB(0, Random(256), Random(256)) );
      SetBkColor (hdc, RGB( 255, Random(256), 128+Random(128)) );
      TextOut (hdc, 20, klient.bottom/2, "Zmień wymiary okienka! (ĄŻŚŹĆĘÓŁŃ)", 34);

      SelectObject (hdc, stara_czcionka);
      DeleteObject (nowa_czcionka);

      EndPaint (hwnd, &ps);
      return 0;
    }
    case WM_DESTROY:
    {
      PostQuitMessage (0);
      return 0;
    }
  }
  return DefWindowProc (hwnd, message, wParam, lParam);
}
