/*
* Plik naglowkowy zawierajacy funkcje glowna programu.
*
*      autor: r.Q
*      licencja: GNU GPL
*
*/
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include "ustawieniaGry.h"
#include "gra.h"
#include "koraliki.h"
#include "gracz.h"
#include "resource.h"
#include "wektor.h"
#include "listaWynikow.h"

#define ID_TIMER         1

enum STANGRY {TABELA, NOWA, PAUZA}; // TABELA to ekran wynikow, NOWA to gra rozpoczeta,
                                    // PAUZA to gra spauzowana
                                   
typedef struct {                   // struktura stanowi pakiet danych wysylanych do procedury okna
                                   // dialogowego nowej gry
        POZ_TRUD trudnosc;
        TRYB tryb;
} NEWGAMEBOX_DATA;

void RysujPauze(HDC, ushort_t&, ushort_t&);
void SprawdzWynik(HWND, POZYCJA*, POZ_TRUD, TRYB, GRACZ*);

LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK NameDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK NewGameDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK HelpDlgProc(HWND, UINT, WPARAM, LPARAM);

TCHAR szAppName[] = "Koraliki";

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
    
    // Sprawdzam czy jest ustawina odpowiednia rozdzielczosc ekranu
    if(GetSystemMetrics(SM_CXSCREEN) < 800) {
        MessageBox(NULL, TEXT("Wymagana minimalna rozdzielczość 800x600"),
                   szAppName, MB_ICONWARNING);
        return (0);
    }
    
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    HACCEL hAccel;
    
    wndclass.style = CS_VREDRAW | CS_HREDRAW;
    wndclass.lpfnWndProc = WinProc;
    wndclass.cbWndExtra = 0;
    wndclass.cbClsExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;
    
    if(!RegisterClass(&wndclass)) {
        MessageBox(NULL, TEXT("Wymagany Windows XP!"), szAppName, MB_ICONERROR);
        return (0);
    }
    
    hwnd = CreateWindow(szAppName,
                        szAppName,
                        WS_OVERLAPPED | WS_SYSMENU,
                        0,
                        0,
                        SCREEN_WIDTH,
                        SCREEN_HEIGHT,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);
                        
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    
    hAccel = LoadAccelerators(hInstance, szAppName);
    
    while(GetMessage(&msg, NULL, 0, 0)) {
        if(!TranslateAccelerator(hwnd, hAccel, &msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    return msg.wParam;
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        //////////////ZMIENNE STERUJACE GRA//////////////////////////////////////
        static int iloscKoralikow;                // ogolna ilosc koralikow
        static int msecNaKlatke;
        static int ileJeszczeKoralikow;           // ile koralikow pozostao do nawleczenia
        //////////////ZMIENNE OBSLUGUJACE PROGRAM///////////////////////////////       
        static HWND hwndPunkty;                   // uchwyt okna wyswietlajacego iosc ruchow
        static ushort_t xObszarGry, yObszarGry;
        
        static POZYCJA* pLista;                   //  wskaznik na tabele wynikow
        static int poziom;                        // zmienna przechowuje numer poziomu
        
        static KORALIK* pKoraliki, *pZnaleziony;  // wskaznik 'pZnaleziony' przechowuje
                                                  // adres koralika, ktory zostal wytypowany
                                                  // jako ten z ktorym nastepuje kolizja
                                                  // (jest przewlekany).
        static GRACZ gracz;
        static WEKTOR* wTor;
        static KIERUNEK kierPrev;                 // zmienna przechowuje poprzedni kierunek gracza
        static KIERUNEK kierNowy;                 // zmienna przechowuje nowa wartosc kierunku,
                                                  // ktora jest zmieniana w trakcie komunikatu klawiatury

        static STANGRY stanGry;                   // zmienna opisuje aktualny stan gry;
        static int xChar, yChar;
        
        static NEWGAMEBOX_DATA ngData;            // inicjalizuje strukture danych
                                                  // aby moc ja wyslac do procedury
                                                  // okna dialogowego
        ////////ZMIENNE NIETRWALE WYKORZYSTYWANE W ROZNYCH MIEJSCACH PROGRAMU/////
        HDC hdc;
        PAINTSTRUCT ps;
        POINT ptTemp;
        TEXTMETRIC tm;
        char szBufor[13];

        switch(message) {
                        case WM_CREATE: {
                             if(!(pLista = PobierzDane())) {
                                         MessageBox(NULL, TEXT("Blad w trakcie zapisu lub odczytu z pliku!"),
                                                    szAppName, MB_ICONERROR);
                                         DestroyWindow(hwnd);
                                         return (0);
                             }
                             // uruchom generator liczb pseudolosowych
                             srand(time(NULL));
                             poziom = 0;
                             // ustawiam obszar gry
                             UstawObszarGry(hwnd, xObszarGry, yObszarGry);
                             SetTimer(hwnd, ID_TIMER, 2000, NULL);
                             hdc = GetDC(hwnd);
                             GetTextMetrics(hdc, &tm);
                             xChar = tm.tmAveCharWidth;
                             yChar = tm.tmHeight + tm.tmExternalLeading;
                             ReleaseDC(hwnd, hdc);
                             // Tworze wektor toru
                             wTor = TworzWektor();
                             pKoraliki = NULL;
                             pZnaleziony = NULL;
                             stanGry = TABELA;
                             // inicjuje strukture danych dla okna dialogowego
                             ngData.trudnosc = LATWY;
                             ngData.tryb = T25K;
                             return (0);
                        }
                        case WM_ACTIVATE: {
                             if(stanGry == NOWA) {
                                        if(LOWORD(wParam) == WA_INACTIVE)
                                               KillTimer(hwnd, ID_TIMER);
                                        else 
                                             SetTimer(hwnd, ID_TIMER, msecNaKlatke, NULL);
                             }
                             return (0);
                        }
                        case WM_INITMENUPOPUP: {
                             if(!lParam) {
                                  switch(stanGry) {
                                       case TABELA: {
                                            EnableMenuItem((HMENU)wParam, IDM_GRA_NOWA, MF_ENABLED);
                                            EnableMenuItem((HMENU)wParam, IDM_GRA_RESET, MF_GRAYED);
                                            EnableMenuItem((HMENU)wParam, IDM_GRA_PAUZA, MF_GRAYED);
                                            EnableMenuItem((HMENU)wParam, IDM_GRA_ZAKONCZ, MF_GRAYED);
                                            return (0);
                                       }
                                       case NOWA: {
                                            EnableMenuItem((HMENU)wParam, IDM_GRA_NOWA, MF_GRAYED);
                                            EnableMenuItem((HMENU)wParam, IDM_GRA_RESET, MF_ENABLED);
                                            EnableMenuItem((HMENU)wParam, IDM_GRA_PAUZA, MF_ENABLED);
                                            EnableMenuItem((HMENU)wParam, IDM_GRA_ZAKONCZ, MF_ENABLED);
                                            return (0);
                                       }
                                  }
                             }
                        break;
                        }
                        case WM_COMMAND: {
                             switch(LOWORD(wParam)) {
                                   case IDM_GRA_NOWA: {
                                      if(DialogBoxParam((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
                                                        TEXT("NewGameBox"), hwnd, NewGameDlgProc, (LPARAM)&ngData)) {
                                             hwndPunkty = CreateWindow(TEXT("static"), TEXT("Ruchów:     0"),
                                                                       WS_CHILD | WS_VISIBLE | SS_CENTER,
                                                                       2, 2, xChar * 14, yChar, hwnd, (HMENU) 1,
                                                                       (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
                                             // ustawiam gre w zaleznosci od wybory gracza
                                             switch(ngData.trudnosc) {
                                                  case LATWY: {
                                                       msecNaKlatke = 300;
                                                       break;
                                                  }
                                                  case SREDNI: {
                                                       msecNaKlatke = 100;
                                                       break;
                                                  }
                                                  case TRUDNY: {
                                                       msecNaKlatke = 50;
                                                       break;
                                                  }
                                             }
                                             switch(ngData.tryb) {
                                                  case T25K: {
                                                       iloscKoralikow = 25;
                                                       break;
                                                  }
                                                  case T50K: {
                                                       iloscKoralikow = 50;
                                                       break;
                                                  }
                                                  case T95K: {
                                                       iloscKoralikow = 95;
                                                       break;
                                                  }
                                             }
                                             // losuje koraliki
                                             pKoraliki = TworzKoraliki(iloscKoralikow, xObszarGry, yObszarGry);
                                             // ustawiam gracza
                                             LosujPozycjeGracza(&gracz, xObszarGry, yObszarGry);
                                             UstawIloscRuchow(&gracz, 0);
                                             kierNowy = kierPrev = gracz.kierunek;
                                             // punkt poczatkowy
                                             ptTemp = gracz.polozenie;
                                             DodajElement(wTor, &ptTemp);
                                             // punkt nastepny
                                             // oba punkty stanowia odcinek toru
                                             DodajElement(wTor, &ptTemp);
                                             KillTimer(hwnd, ID_TIMER);
                                             SetTimer(hwnd, ID_TIMER, msecNaKlatke, NULL);
                                             stanGry = NOWA;  
                                             ileJeszczeKoralikow = iloscKoralikow;
                                             InvalidateRect(hwnd, NULL, TRUE);
                                      }
                                      break;
                                   }
                                   case IDM_GRA_PAUZA: {
                                      switch(stanGry) {
                                          case NOWA: {
                                               KillTimer(hwnd, ID_TIMER);
                                               stanGry = PAUZA;
                                               PlaySound("PAUZA_WL_SND", (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
                                                         SND_RESOURCE | SND_ASYNC);
                                               break;
                                          }
                                          case PAUZA: {
                                               SetTimer(hwnd, ID_TIMER, msecNaKlatke, NULL);
                                               stanGry = NOWA;
                                               PlaySound("PAUZA_WYL_SND", (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
                                                         SND_RESOURCE | SND_ASYNC);
                                               break;
                                          }
                                      }
                                      InvalidateRect(hwnd, NULL, TRUE);
                                      return (0);
                                 }
                                 case IDM_GRA_RESET: {
                                      // wywalam koraliki
                                      free(pKoraliki);
                                      // losuje nowe koraliki
                                      pKoraliki = TworzKoraliki(iloscKoralikow, xObszarGry,
                                                                yObszarGry);
                                      pZnaleziony = NULL;
                                      // ustawiam na nowo gracza
                                      LosujPozycjeGracza(&gracz, xObszarGry, yObszarGry);
                                      UstawIloscRuchow(&gracz, 0);
                                      kierNowy = kierPrev = gracz.kierunek;
                                      ptTemp = gracz.polozenie;
                                      // czyszcze wektor i go usupelniam
                                      CzyscWektor(wTor);
                                      DodajElement(wTor, &ptTemp);
                                      DodajElement(wTor, &ptTemp);
                                      ileJeszczeKoralikow = iloscKoralikow;
                                      wsprintf(szBufor, "Ruchów: %5d", 0);
                                      SetWindowText(GetDlgItem(hwnd, 1), szBufor);
                                      InvalidateRect(hwnd, NULL, TRUE);
                                      break;
                                 }
                                 case IDM_GRA_ZAKONCZ: {
                                      int msecTimer;
                                      msecTimer = msecNaKlatke;
                                      // wstrzymuje gre
                                      KillTimer(hwnd, ID_TIMER);
                                      if(MessageBox(NULL, TEXT("Czy napewno chcesz zakończyć grę, i powrócić do ekranu głównego?"),
                                                    szAppName, MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL) == IDYES) {
                                           // wywalam koraliki
                                           free(pKoraliki);
                                           pKoraliki = NULL;
                                           pZnaleziony = NULL;
                                           // czyszcze wektor i go usupelniam
                                           CzyscWektor(wTor);
                                           DestroyWindow(hwndPunkty);
                                           // zatrzymuje timer
                                           KillTimer(hwnd, ID_TIMER);
                                           msecTimer = 2000;
                                           stanGry = TABELA;
                                           InvalidateRect(hwnd, NULL, TRUE);
                                      }
                                      // wznawiam gre
                                      SetTimer(hwnd, ID_TIMER, msecTimer, NULL);
                                      break;
                                 }
                                 case IDM_GRA_WYJSCIE: {
                                      SendMessage(hwnd, WM_CLOSE, 0, 0);
                                      break;
                                 }
                                 case IDM_POMOC_POMOC: {
                                      DialogBox((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
                                                TEXT("HelpBox"), hwnd, HelpDlgProc);
                                                break;
                                 }
                             }
                             return (0);
                        }
                        case WM_TIMER: {
                             hdc = GetDC(hwnd);
                             switch(stanGry) {
                                    case TABELA: {
                                         AktualizujTabele(hwnd, hdc, xChar, yChar);
                                         poziom = (poziom + 1) % 3;
                                         break;
                                    }
                                    case NOWA: {
                                         UstawIloscRuchow(&gracz, PobierzIloscRuchow(&gracz) + 1);
                                         wsprintf(szBufor, "Ruchów: %5d", PobierzIloscRuchow(&gracz));
                                         SetWindowText(GetDlgItem(hwnd, 1), szBufor);
                                         SetROP2(hdc, R2_NOT);
                                         RysujGracza(hdc, &gracz);
                                         AktualizujGracza(hwnd, hdc, &gracz, pKoraliki, wTor, xObszarGry,
                                                          yObszarGry, kierPrev, kierNowy, pZnaleziony,
                                                          iloscKoralikow, ileJeszczeKoralikow);
                                         kierPrev = gracz.kierunek;
                                         RysujGracza(hdc, &gracz);
                                         if(!ileJeszczeKoralikow) {
                                               KillTimer(hwnd, ID_TIMER);
                                               MessageBox(NULL, TEXT("Nawlokłeś wszystkie koraliki!"), szAppName, MB_ICONINFORMATION | MB_TASKMODAL);
                                               SprawdzWynik(hwnd, pLista, ngData.trudnosc, ngData.tryb, &gracz);
                                               // wywalam koraliki
                                               free(pKoraliki);
                                               pKoraliki = NULL;
                                               pZnaleziony = NULL;
                                               // czyszcze wektor i go usupelniam
                                               CzyscWektor(wTor);
                                               DestroyWindow(hwndPunkty);
                                               SetTimer(hwnd, ID_TIMER, 2000, NULL);
                                               stanGry = TABELA;
                                               ileJeszczeKoralikow = iloscKoralikow;
                                               InvalidateRect(hwnd, NULL, TRUE);
                                         }
                                         break;
                                    }
                            }
                            ReleaseDC(hwnd, hdc);
                            return (0);
                        }
                        case WM_KEYDOWN: {
                             // przetwarzaj komunikat tylko w trakcie gry
                             if(stanGry == NOWA) {
                                  switch(wParam) {
                                       case VK_UP: {
                                            if(gracz.kierunek % 2 == 0) {
                                                   kierNowy = GORA;
                                            }
                                            break;
                                       }
                                       case VK_DOWN: {
                                            if(gracz.kierunek % 2 == 0) {
                                                   kierNowy = DOL;
                                            }
                                            break;
                                       }
                                       case VK_LEFT: {
                                            if(gracz.kierunek % 2 != 0) {
                                                   kierNowy = LEWO;
                                            }
                                            break;
                                       }
                                       case VK_RIGHT: {
                                            if(gracz.kierunek % 2 != 0) {
                                                   kierNowy = PRAWO;
                                            }
                                            break;
                                       }
                                  }
                             }
                             return (0);
                        }
                        case WM_PAINT: {
                             hdc = BeginPaint(hwnd, &ps);
                             switch(stanGry) {
                                    case TABELA: {
                                         OdczytajPozTrud(hdc, pLista, (POZ_TRUD)poziom);
                                         break;
                                    }
                                    case PAUZA:
                                    case NOWA: {
                                         RysujKoraliki(hdc, pKoraliki, iloscKoralikow);
                                         RysujNitke(hdc, wTor, xObszarGry, yObszarGry);
                                         SetROP2(hdc, R2_NOT);
                                         RysujGracza(hdc, &gracz);
                                         if(stanGry == PAUZA)
                                                    RysujPauze(hdc, xObszarGry, yObszarGry);
                                         break;
                                    }
                             }
                             EndPaint(hwnd, &ps);
                             return (0);
                        }
                        case WM_CLOSE: {
                             switch(stanGry) {
                                  case TABELA: {
                                       if(MessageBox(NULL, TEXT("Czy chcesz opuścić program?"),
                                              szAppName, MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL) == IDYES) {
                                                         DestroyWindow(hwnd);
                                                         KillTimer(hwnd, ID_TIMER);
                                              }
                                       break;
                                  }
                                  case NOWA: {
                                       KillTimer(hwnd, ID_TIMER);
                                       if(MessageBox(NULL, TEXT("Czy chcesz opuścić program?"),
                                              szAppName, MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL) == IDYES) {
                                                         DestroyWindow(hwnd);
                                                         return (0);
                                       }
                                       SetTimer(hwnd, ID_TIMER, msecNaKlatke, NULL);
                                       break;
                                  }
                                  case PAUZA: {
                                       if(MessageBox(NULL, TEXT("Czy chcesz opuścić program?"),
                                              szAppName, MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL) == IDYES)
                                                         DestroyWindow(hwnd);
                                       break;
                                  }
                             }
                             return (0);
                        }
                        case WM_DESTROY: {
                             if(pKoraliki)
                                  free(pKoraliki);
                             KasujWektor(wTor);
                             free(wTor);
                             ZapiszListe(pLista);
                             free(pLista);
                             PostQuitMessage(0);
                             return (0);
                        }
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
}
void RysujPauze(HDC hdc, ushort_t& xObszarGry, ushort_t& yObszarGry) {
     RECT rc;
     int i, prevROP2;
     prevROP2 = SetROP2(hdc, R2_WHITE);
     SetBkMode(hdc, TRANSPARENT);
     // rysuje duzo pionowych linii blisko siebie, aby dac wrazenie rozjasnienia
     for(i = 0; i < xObszarGry; i += 2) {
           MoveToEx(hdc, i, 0, NULL);
           LineTo(hdc, i, yObszarGry);
     }
     SetRect(&rc, 0, 0, xObszarGry, yObszarGry);
     DrawText(hdc, "PAUZA", 5, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
     SetROP2(hdc, prevROP2);
}
void SprawdzWynik(HWND hwnd, POZYCJA* pLista, POZ_TRUD trudnosc, TRYB tryb, GRACZ* gracz) {
     int index;
     char nazwa[10];
     index = CzyNowyRekord(pLista, trudnosc, tryb, gracz->ileRuchow);
     if(index >= 0) {
              PlaySound("tada.wav", NULL, SND_FILENAME | SND_ASYNC);
              DialogBoxParam((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
                              TEXT("NameBox"), hwnd, NameDlgProc, (LPARAM)nazwa);
              DodajRekord(pLista, trudnosc, tryb, index, nazwa, gracz->ileRuchow);
     }
}
BOOL CALLBACK NameDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
     HWND hwndEdit;
     int dlugosc;
     static char* pChar;
     switch(message) {
                     case WM_INITDIALOG: {
                          pChar = (char*)lParam;
                          return TRUE;
                     }
                     case WM_COMMAND: {
                          switch(LOWORD(wParam)) {
                               case IDC_EDIT: {
                                    if(HIWORD(wParam) == EN_ERRSPACE || HIWORD(wParam) == EN_MAXTEXT)
                                         MessageBox(hwnd, TEXT("Brak miejsca!"), szAppName, MB_OK | MB_ICONSTOP);
                                    return TRUE;
                               }
                               case IDOK: {
                                    hwndEdit = GetDlgItem(hwnd, IDC_EDIT);
                                    // pobierz dlugosc wpisanego tekstu
                                    dlugosc = SendMessage(hwndEdit, EM_LINELENGTH, 1, 0);
                                    if(dlugosc == 0) {
                                          MessageBox(hwnd, TEXT("Nic nie wpisano!"), szAppName, MB_OK | MB_ICONWARNING);
                                          return FALSE;
                                    }
                                    else if(dlugosc > 9) {
                                         MessageBox(hwnd, TEXT("Zbyt dlugi napis!"), szAppName, MB_OK | MB_ICONWARNING);
                                         return FALSE;
                                    }
                                    SendMessage(hwndEdit, EM_GETLINE, 0, (LPARAM)pChar);
                                    EndDialog(hwnd, 0);
                                    return TRUE;
                               }
                           }
                     }
     }
     return FALSE;
}
BOOL CALLBACK NewGameDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
     static NEWGAMEBOX_DATA * pNewGame;
     int i;
     switch(message) {
          case WM_INITDIALOG: {
               pNewGame = (NEWGAMEBOX_DATA*)lParam;
               CheckRadioButton(hwnd, IDC_TRYB_25K, IDC_TRYB_95K, IDC_TRYB_25K);
               CheckRadioButton(hwnd, IDC_POZIOM_LATWY, IDC_POZIOM_TRUDNY, IDC_POZIOM_LATWY);
               return TRUE;
          }
          case WM_COMMAND: {
               switch(LOWORD(wParam)) {
                    case IDC_TRYB_25K:
                    case IDC_TRYB_50K:
                    case IDC_TRYB_95K: {
                         CheckRadioButton(hwnd, IDC_TRYB_25K, IDC_TRYB_95K, LOWORD(wParam));
                         return TRUE;
                    }
                    case IDC_POZIOM_LATWY:
                    case IDC_POZIOM_SREDNI:
                    case IDC_POZIOM_TRUDNY: {
                         CheckRadioButton(hwnd, IDC_POZIOM_LATWY, IDC_POZIOM_TRUDNY, LOWORD(wParam));
                         return TRUE;
                    }
                    case IDOK: {
                         for(i = IDC_POZIOM_LATWY; i <= IDC_POZIOM_TRUDNY; i++) {
                               if(IsDlgButtonChecked(hwnd, i))
                                   pNewGame->trudnosc = (POZ_TRUD)(i - IDC_POZIOM_LATWY);
                         }
                         for(i = IDC_TRYB_25K; i <= IDC_TRYB_95K; i++) {
                               if(IsDlgButtonChecked(hwnd, i))
                                   pNewGame->tryb = (TRYB)(i - IDC_TRYB_25K);
                         }
                         EndDialog(hwnd, 1);
                         return TRUE;
                    }
                    case IDCANCEL: {
                         EndDialog(hwnd, 0);
                         return TRUE;
                    }
               }
          }
     }
     return FALSE;
}
BOOL CALLBACK HelpDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
     switch(message) {
                     case WM_INITDIALOG: {
                          return TRUE;
                     }
                     case WM_COMMAND: {
                          switch(LOWORD(wParam)) {
                              case IDOK:
                              case IDCANCEL: {
                                   EndDialog(hwnd, 0);
                                   return TRUE;
                              }
                          }
                     }
     }
     return FALSE;
}
