#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <ctime>
#include <ctype.h>

#include <gdiplus/gdiplus.h>
#pragma comment (lib, "gdiplus.lib")

#include "resource.h"

int cx, cy;
int cell, cells=20, cellOff;
int shiftStep;
bool load=true;
bool noRest=false;
bool blur_on=false;

// Declare Windows procedure
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
int gFunsterStil;
HWND hwnd, hwndB;// This is the handle for our window
HINSTANCE gThisInstance;
MSG messages;// Here messages to the application are saved
WNDCLASSEX wincl;// Data structure for the windowclass
RECT Rect;
HDC hDC;
COLORREF txtCol=RGB (255, 255, 255);
COLORREF txtColG=RGB (175, 175, 175);
COLORREF bkCol=RGB (100, 100, 100);
HBRUSH bg=CreateSolidBrush (bkCol);
HBRUSH bgB=CreateSolidBrush (txtCol);
HPEN pen=CreatePen (PS_SOLID, 1, bkCol);
HFONT hFont;
PAINTSTRUCT PaintStruct;

// Make the class name into a global variable
char szClassName []="WindowsApp";
char title []=" PicViewer";

char url [_MAX_PATH], pDir [_MAX_PATH], pF [50000] [256];
int url_l=0;
int pFc=0, pFn=-1;
int infoOn=0;
int px, py, pl, pt, pla=0, pta=0;
float pxs, pys;
int stepX=0, stepY=0, stepN=0;
int cFrames;
bool slide=false;
bool full=false;
const unsigned int TIMER_SLIDE=1, TIMER_MESS=2, TIMER_CUR=5;
char mess [256];
bool messOn=false;
bool ctrl=false;
bool shift=false;
bool copyDirIs=false;
int hideCur=0;

ULONG_PTR gdiplusToken; 
Gdiplus::Graphics * gDC;
Gdiplus::Image * imagesH;

POINT mypoint;



void messPrint ()
{
 hDC=GetDC (hwnd);

 SelectObject (hDC, pen);
 SelectObject (hDC, bg);
 Rectangle(hDC, 0, 0, cx, cy);

 SelectObject (hDC, hFont);
 SetBkColor (hDC, bkCol);
 SetTextColor (hDC, txtCol);
 SetRect (&Rect, 0, 0, cx, cy);
 DrawText (hDC, mess, strlen (mess), &Rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

 ReleaseDC (hwnd, hDC);
}

void messPrintP ()
{
 messPrint ();

 messOn=true;
 SetTimer (hwnd, TIMER_MESS, 2500, NULL);
}



void picture (bool reload=false)
{
 bool fileIs=true;

 if (reload==true)
 {
  FILE * file;
  file=fopen (url, "r");
  if (file==NULL)
   fileIs=false;
  fclose (file);

  if (fileIs==true)
  {
   delete imagesH;

   WCHAR ts [256];

   MultiByteToWideChar (CP_ACP, 0, url, -1, ts, 256);

   imagesH=new Gdiplus::Image (ts, true);
   px=imagesH->GetWidth ();
  }
 }
 if (fileIs==true && px>0)
 {
  cFrames=imagesH->GetFrameCount (&Gdiplus::FrameDimensionTime);
    
  hDC=GetDC (hwnd);

  SelectObject (hDC, pen);
  SelectObject (hDC, bg);
  Rectangle (hDC, 0, 0, cx+1, cy+1);

  if (reload==true)
   py=imagesH->GetHeight ();

  if ((px>cx || py>cy) && full==false)
  {
   if (px/cx>py/cy)
   {
    pxs=cx+1;
    pys=py/((float)px/(float)(cx+1));
   }
   else
   {
    pys=cy+1;
    pxs=px/((float)py/(float)(cy+1));
   }
  }
  else
  {
   if (stepN!=0)
   {
    if (cx>cy)
     stepX=cy/5;
    else
     stepX=cx/5;
    stepY=stepX;

    if (px>py)
     stepY*=(float)py/(float)px;
    else
     stepX*=(float)px/(float)py;

    pxs=px+stepX*stepN;
    pys=py+stepY*stepN;
   }
   else
   {
    pxs=px;
    pys=py;
   }
  }

  pl=(cx-pxs)/2;
  pt=(cy-pys)/2;

  gDC=new Gdiplus::Graphics (hDC);
  gDC->SetPageUnit(Gdiplus::UnitPixel);
  gDC->SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
  gDC->SetCompositingQuality(Gdiplus::CompositingQualityAssumeLinear);
  gDC->SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);
  gDC->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
  gDC->SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);

  Gdiplus::RectF bounds(pl+pla, pt+pta, pxs, pys);
  Gdiplus::ImageAttributes attr;
  attr.SetWrapMode(Gdiplus::WrapModeTile);

  gDC->DrawImage (imagesH, bounds, 0, 0, px, py, Gdiplus::UnitPixel, &attr);

  DeleteObject (&attr);
  DeleteObject (&bounds);

  ReleaseDC (hwnd, hDC);
 }
 else
 {
  char name [256];
  memset (name, 0, 256);
  int i, i2, c=0;

  for (i=strlen (url)-1; i>0; i--)
  {
   if (url [i]=='\\')
    break;
  }
  for (i2=i+1; i2<strlen (url); i2++)
  {
   name [c]=url [i2];
   c++;
  }

  if (fileIs==true)
   sprintf (mess, "Файл \"%s\" не распознан", name);
  else
   sprintf (mess, "Файл \"%s\" не найден", name);
  messPrint ();
 }
}



void info ()
{
 int i, lines, line=1;
 char txtL [32] [256];

 if (infoOn==3)
 {
  if (cFrames>1)
  {
   char txtLa [] [256]={"Файл: ", "Дата: ", "Длина: ", "Размер: ", "Кадры: ", "Место: "};
   lines=sizeof (txtLa)/256;
   for (i=0; i<lines; i++)
    memcpy (txtL [i*2], txtLa [i], 256);
  }
  else
  {
   char txtLa [] [256]={"Файл: ", "Дата: ", "Длина: ", "Размер: ", "Место: "};
   lines=sizeof (txtLa)/256;
   for (i=0; i<lines; i++)
    memcpy (txtL [i*2], txtLa [i], 256);
  }

  if (pFn==-1)
   sprintf (txtL [line*2-1], "не найден");
  else
   memcpy (txtL [line*2-1], pF [pFn], 256);

  line++;

  WIN32_FIND_DATA FindFileData;
  HANDLE hf;
  FILETIME creationTime;
  SYSTEMTIME sysTime;
  hf=FindFirstFile (url, &FindFileData);
  if (hf!=INVALID_HANDLE_VALUE)
  {
   creationTime=FindFileData.ftLastWriteTime;
   FileTimeToSystemTime (&creationTime, &sysTime);
   char month [] [10]={"января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"};
   sprintf (txtL [line*2-1], "%d %s %d", sysTime.wDay, month [sysTime.wMonth-1], sysTime.wYear);
  }

  line++;

  FILE * file;
  int size;
  file=fopen (url, "r");
  if (file!=NULL)
  {
   fseek (file, 0, SEEK_END);// seek to end of file
   size=ftell (file);// get current file pointer
  }
  fclose (file);

  if (size<1024)
   sprintf (txtL [line*2-1], "%d байт", size);
  else if (size<1024*1024)
   sprintf (txtL [line*2-1], "%d Кб", size/1024);
  else if (size<1024*1024*1024)
  {
   int d=size*10/(1024*1024)-size/(1024*1024)*10;
   if (d!=0)
    sprintf (txtL [line*2-1], "%d,%d Мб", size/(1024*1024), d);
   else
    sprintf (txtL [line*2-1], "%d Мб", size/(1024*1024));
  }

  line++;

  sprintf (txtL [line*2-1], "%d x %d", px, py);

  line++;

  if (cFrames>1)
  {
   sprintf (txtL [line*2-1], "%d", cFrames);
   line++;
  }

  if (pFn==-1)
   sprintf (txtL [line*2-1], "? / %d");
  else
   sprintf (txtL [line*2-1], "%d / %d", pFn+1, pFc);
 }
 else
 {
  char txtLa [] [256]={
             "Просмотр: ", "(ctrl +) влево, вправо",
    "К началу, в конец: ", "ctrl + home / end",
            "Слайд-шоу: ", "enter",
              "Поворот: ", "вверх, вниз",
        "Полный размер: ", "пробел",
 "Увеличить, уменьшить: ", "плюс, минус",
                "Сдвиг: ", "shift + клавиши-стрелки",
                "Копия: ", "c",
              "О файле: ", "i",
              "Справка: ", "f1, h",
                "Выход: ", "esc"
  };

  lines=sizeof (txtLa)/256/2;
  for (i=0; i<lines*2; i++)
   memcpy (txtL [i], txtLa [i], 256);
 }

 char txtA [256];
 sprintf (txtA, "PicViewer 2015-17 %c Маркичев Д. И. ", 169);
 char txtB [256]={"Нажмите любую клавишу для возврата... "};

 hDC=GetDC (hwnd);

 SelectObject (hDC, pen);
 SelectObject (hDC, bg);
 Rectangle(hDC, 0, 0, cx, cy);
 SetBkColor (hDC, bkCol);
 SetTextColor (hDC, txtCol);
 SelectObject (hDC, hFont);

 for (i=0; i<lines; i++)
 {
  SetRect (&Rect, 0, cellOff+cell*((cells-lines)/2+i), cx/2, cellOff+cell*((cells-lines)/2+i+1));
  DrawText (hDC, txtL [i*2], strlen (txtL [i*2]), &Rect, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
 }

 SetTextColor (hDC, txtColG);
 for (i=0; i<lines; i++)
 {
  SetRect (&Rect, cx/2, cellOff+cell*((cells-lines)/2+i), cx, cellOff+cell*((cells-lines)/2+i+1));
  DrawText (hDC, txtL [i*2+1], strlen (txtL [i*2+1]), &Rect, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
 }

 SetRect (&Rect, cx/2, cellOff+cell*(cells-2), cx, cellOff+cell*(cells-1));
 if (infoOn!=1)
  DrawText (hDC, txtB, strlen (txtB), &Rect, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
 else
  DrawText (hDC, txtA, strlen (txtA), &Rect, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);

 ReleaseDC (hwnd, hDC);
}



void screenSet ()
{
 cx=(LONG)::GetSystemMetrics( SM_CXSCREEN );
 cy=(LONG)::GetSystemMetrics( SM_CYSCREEN );

 DeleteObject (hFont);
 if (cx>cy)
 {
  shiftStep=cy/5;
  hFont=CreateFont (cy/30, 0, 0, 0, FW_EXTRABOLD, false, false, false, RUSSIAN_CHARSET, false, false, ANTIALIASED_QUALITY, false, "Arial");
  cell=cy/cells;
  cellOff=0;
 }
 else
 {
  shiftStep=cx/5;
  hFont=CreateFont (cx/30, 0, 0, 0, FW_EXTRABOLD, false, false, false, RUSSIAN_CHARSET, false, false, ANTIALIASED_QUALITY, false, "Arial");
  cell=cx/cells;
  cellOff=(cy-cx)/2;
 }
}

void screenUp ()
{
 noRest=true;

 hwndB = CreateWindowEx (
  0,// Extended possibilites for variation
  szClassName,// Classname
  title,// Title Text
  WS_POPUP,
  -1,
  -1,
  cx+2,// The programs width
  cy+2,// and height in pixels
  HWND_DESKTOP,// The window is a child-window to desktop
  NULL,// No menu
  gThisInstance,// Program Instance handler
  NULL// No Window Creation data
 );

 ShowWindow (hwndB, gFunsterStil);
 ShowWindow (hwnd, 0);
 hwnd=hwndB;

 noRest=false;
}

void copyPic ()
{
 if (copyDirIs==false)
 {
  char copyDir [_MAX_PATH];
  sprintf (copyDir, "%s%s", pDir, "PicViewer");
  mkdir (copyDir);
  copyDirIs=true;
 }

 char copyFile [_MAX_PATH];
 sprintf (copyFile, "%s%s%s", pDir, "PicViewer\\", pF [pFn]);

 bool r=CopyFile (url, copyFile, false);
 if (r)
 {
  sprintf (mess, "Файл скопирован:  \"PicViewer\\%s\"", pF [pFn]);
  messPrintP ();
 }
 else
 {
  sprintf (mess, "Ошибка при копировании файла");
  messPrintP ();
 }
}



int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
 gThisInstance=hThisInstance;
 gFunsterStil=nFunsterStil;

 Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
 GdiplusStartup (&gdiplusToken, &gdiplusStartupInput, NULL);

 // The Window structure
 wincl.hInstance=hThisInstance;
 wincl.lpszClassName=szClassName;
 wincl.lpfnWndProc=WindowProcedure;// This function is called by windows
 wincl.style=CS_DBLCLKS;// Catch double-clicks
 wincl.cbSize=sizeof (WNDCLASSEX);
 wincl.hIcon=LoadIcon (hThisInstance, MAKEINTRESOURCE(ID_PIC));
 wincl.hIconSm=LoadIcon (hThisInstance, MAKEINTRESOURCE(ID_PIC));
 wincl.hCursor=LoadCursor (NULL, IDC_ARROW);
 wincl.lpszMenuName=NULL;// No menu
 wincl.cbClsExtra=0;// No extra bytes after the window class
 wincl.cbWndExtra=0;// structure or the window instance
 wincl.hbrBackground=bg;

 // Register the window class, and if it fails quit the program
 if (!RegisterClassEx (&wincl))
  return 0;

 screenSet ();

 hwnd = CreateWindowEx (
  0,// Extended possibilites for variation
  szClassName,// Classname
  title,// Title Text
  WS_POPUP,
  -1,
  -1,
  cx+2,// The programs width
  cy+2,// and height in pixels
  HWND_DESKTOP,// The window is a child-window to desktop
  NULL,// No menu
  gThisInstance,// Program Instance handler
  NULL// No Window Creation data
 );

 ShowWindow (hwnd, gFunsterStil);

 SetTimer (hwnd, TIMER_CUR, 500, NULL);

 int i, c=0;
 bool qt2=false;
 memset (url, 0, _MAX_PATH);

 for (c=0; c<_MAX_PATH; c++)
 {
  if (lpszArgument [c]==34)
   qt2=true;
  else if (lpszArgument [c]==0)
   break;
 }

 if (c>2)
 {
  if (qt2==true)
  {
   for (i=0; i<c-2; i++)
    url [i]=lpszArgument [i+1];
   url_l=c-2;
  }
  else
  {
   for (i=0; i<c; i++)
    url [i]=lpszArgument [i];
   url_l=c;
  }
 }

 if (strlen (url)>3)
  picture (true);
 else
 {
  infoOn=1;
  info ();
 }

 char pFile [256];
 int pD_l=0;
 memset (pDir, 0, _MAX_PATH);
 memset (pFile, 0, 256);
 for (i=url_l-1; i>=0 && pD_l==0; i--)
 {
   if (url [i]=='\\')
    pD_l=i+1;
 }
 memcpy (pDir, url, pD_l);

 for (i=pD_l; i<url_l; i++)
  pFile [i-pD_l]=url [i];


 char pExt [] [5]={"gif", "jpg", "jpeg", "jpe", "jfif", "png", "tif", "tiff", "ico", "bmp"};

 WIN32_FIND_DATA FindFileData;
 HANDLE hf;

 char pPath [_MAX_PATH];
 memset (pPath, 0, _MAX_PATH);
 sprintf (pPath, "%s%s", pDir, "*.*");
 hf=FindFirstFile (pPath, &FindFileData);

 if (hf!=INVALID_HANDLE_VALUE)
 {
  i=0;
  int i2, l=0, l2;
  while (true)
  {
   if (FindFileData.dwFileAttributes!=FILE_ATTRIBUTE_DIRECTORY)
   {
    l=strlen (FindFileData.cFileName);

    if (!strcmp (FindFileData.cFileName, pFile))
    {
     pFn=pFc;
     sprintf (pF [pFc], "%s", FindFileData.cFileName);
     pFc++;
    }
    else
    {
     for (i=0; i<sizeof (pExt)/5; i++)
     {
      l2=strlen (pExt [i]);
      c=0;
      for (i2=0; i2<l2; i2++)
      {
       if (FindFileData.cFileName [l-l2+i2]==pExt [i] [i2] || FindFileData.cFileName [l-l2+i2]==toupper (pExt [i] [i2]))
        c++;
      }
      if (c==l2)
      {
       sprintf (pF [pFc], "%s", FindFileData.cFileName);
       pFc++;
      }
     }
    }
   }

   if (FindNextFile(hf, &FindFileData)==0 || pFc>=50000-1)
    break;
  }
 }



 // Run the message loop. It will run until GetMessage() returns 0
 while (GetMessage (&messages, NULL, 0, 0))
 {
  // Translate virtual-key messages into character messages
  TranslateMessage (&messages);
  // Send message to WindowProcedure
  DispatchMessage (&messages);
 }

 // The program return-value is 0 - The value that PostQuitMessage() gave
 return messages.wParam;
}



// This function is called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch (message)// handle the messages
 {
  case WM_KEYDOWN:
   if (hideCur>=10)
   {
    ShowCursor (false);
    hideCur=0;
   }

   if (infoOn>1)
   {
    infoOn=0;
    picture ();
    break;
   }
   if (slide==true)
   {
    KillTimer (hwnd, TIMER_SLIDE);
    slide=false;

    sprintf (mess, "Слайд-шоу выключено");
    messPrintP ();
    break;
   }
   if (messOn==true)
   {
    KillTimer (hwnd, TIMER_MESS);
    messOn=false;

    picture ();
    break;
   }

   if (wParam==VK_ESCAPE)
   {
    Gdiplus::GdiplusShutdown (gdiplusToken);
    PostQuitMessage (0);// send a WM_QUIT to the message queue
    break;
   }
   else if (infoOn==1)
    break;

   if (wParam==VK_F1 || wParam==72)
   {
    if (infoOn==0)
    {
     infoOn=2;
     info ();
    }
   }

   switch (wParam)
   {
    case 73:
     if (infoOn==0)
     {
      infoOn=3;
      info ();
     }
    break;

    case 67:
     copyPic ();
    break;

    case VK_CONTROL:
     ctrl=true;
    break;

    case VK_SHIFT:
     shift=true;
    break;

    case VK_LEFT:
     if (shift==true)
     {
      if (pl+pla<0 && px>0)
      {
       pla+=shiftStep;
       if (pl+pla>0)
        pla=-pl;
       picture ();
      }
     }
     else if (((pFn>0 || pFn==-1) && pFc>0 && ctrl==false) || (pFn>pFc/25-1 && pFc>100 && ctrl==true))
     {
      pla=0;
      pta=0;
      infoOn=0;
      if (ctrl==true)
       pFn-=pFc/25;
      else if (pFn==-1)
       pFn=0;
      else
       pFn--;
      memset (url, 0, _MAX_PATH);
      sprintf (url, "%s%s", pDir, pF [pFn]);
      picture (true);
     }
    break;

    case VK_RIGHT:
     if (shift==true)
     {
      if (pl+pla+pxs>cx && px>0)
      {
       pla-=shiftStep;
       if (pl+pla+pxs<cx)
        pla=cx-(pl+pxs);
       picture ();
      }
     }
     else if ((pFn<pFc-1 && ctrl==false) || (pFn<pFc-pFc/25-1 && pFc>100 && ctrl==true))
     {
      pla=0;
      pta=0;
      infoOn=0;
      if (ctrl==true)
       pFn+=pFc/25;
      else
       pFn++;
      memset (url, 0, _MAX_PATH);
      sprintf (url, "%s%s", pDir, pF [pFn]);
      picture (true);
     }
    break;

    case VK_UP:
     if (shift==true)
     {
      if (pt+pta<0 && px>0)
      {
       pta+=shiftStep;
       if (pt+pta>0)
        pta=-pt;
       picture ();
      }
     }
    break;

    case VK_DOWN:
     if (shift==true)
     {
      if (pt+pta+pys>cy && px>0)
      {
       pta-=shiftStep;
       if (pt+pta+pys<cy)
        pta=cy-(pt+pys);
       picture ();
      }
     }
    break;

    case VK_HOME:
     if ((pFn>0 || pFn==-1) && pFc>0 && ctrl)
     {
      pla=0;
      pta=0;
      infoOn=0;
      pFn=0;
      memset (url, 0, _MAX_PATH);
      sprintf (url, "%s%s", pDir, pF [pFn]);
      picture (true);
     }
    break;

    case VK_END:
     if (pFn<pFc-1 && ctrl)
     {
      pla=0;
      pta=0;
      infoOn=0;
      pFn=pFc-1;
      memset (url, 0, _MAX_PATH);
      sprintf (url, "%s%s", pDir, pF [pFn]);
      picture (true);
     }
    break;

    case VK_RETURN:
     if (pFc>1)
     {
      pla=0;
      pta=0;
      infoOn=0;

      sprintf (mess, "Включено слайд-шоу");
      messPrint ();

      slide=true;
      SetTimer (hwnd, TIMER_SLIDE, 5000, NULL);
     }
     else
     {
      sprintf (mess, "Недостаточно изображений");
      messPrint ();

      messOn=true;
      SetTimer (hwnd, TIMER_MESS, 2500, NULL);
     }
    break;

    case VK_SPACE:
     if (full==false)
      full=true;
     else if (full==true)
      full=false;

     if (px>cx || py>cy)
     {
      pla=0;
      pta=0;
      picture ();
     }
    break;
   }

   if ((wParam==VK_UP || wParam==188) && shift==false && px>0)
   {
    pla=0;
    pta=0;

    imagesH->RotateFlip (Gdiplus::Rotate270FlipNone);
    int t=px;
    px=py;
    py=t;

    picture ();
   }

   if ((wParam==VK_DOWN || wParam==190) && shift==false && px>0)
   {
    pla=0;
    pta=0;

    imagesH->RotateFlip (Gdiplus::Rotate90FlipNone);
    int t=px;
    px=py;
    py=t;

    picture ();
   }

   if (wParam==107 || wParam==187)
   {
    if (stepN<7 && px>0 && !(full==false && (px>cx || py>cy)))
    {
     pla=0;
     pta=0;
     stepN++;
     picture ();
    }
   }
   if (wParam==109 || wParam==189)
   {
    if (stepN>0 && px>0 && !(full==false && (px>cx || py>cy)))
    {
     pla=0;
     pta=0;
     stepN--;
     picture ();
    }
   }

  break;

  case WM_KEYUP:

   switch (wParam)
   {
    case VK_CONTROL:
     ctrl=false;
    break;

    case VK_SHIFT:
     shift=false;
    break;
   }

  break;

  case WM_TIMER:
 
   switch (wParam)
   {
    case TIMER_SLIDE:
     if (pFn<pFc-1)
      pFn++;
     else
      pFn=0;
     memset (url, 0, _MAX_PATH);
     sprintf (url, "%s%s", pDir, pF [pFn]);
     picture (true);
    break;

    case TIMER_MESS:
     KillTimer (hwnd, TIMER_MESS);
     messOn=false;
     picture ();
    break;

    case TIMER_CUR:
     KillTimer (hwnd, TIMER_CUR);
     GetCursorPos (&mypoint);
     SetCursorPos (mypoint.x, mypoint.y);
     ShowCursor (false);
    break;
   }

  break;

  case WM_SIZE:

   switch (wParam)
   {
    case SIZE_RESTORED:
     if (noRest==true)
      break;

     if (load==false)
     {
      screenSet ();
      screenUp ();
     }
    break;
   }

  break;

  case WM_MOUSEMOVE:
   hideCur++;
   if (hideCur==10)
    ShowCursor (true);
  break;

  case WM_KILLFOCUS:

   blur_on=true;
   break;

  case WM_SETFOCUS:

   blur_on=false;
   break;

  case WM_PAINT:

   BeginPaint (hwnd, &PaintStruct);

   if (!load)
   {
    if (infoOn!=0)
     info ();
    else
     picture ();
   }
   else
    load=false;

   EndPaint (hwnd, &PaintStruct);
   break;

  case WM_DESTROY:
   Gdiplus::GdiplusShutdown (gdiplusToken);
   PostQuitMessage (0);// send a WM_QUIT to the message queue
  break;

  default:// for messages that we don't deal with
  return DefWindowProc (hwnd, message, wParam, lParam);
 }

 return 0;
}