//****************************************
#include <stdio.h>
#include <math.h>

#define pi       3.1416
#define ID_TM_MAIN    100
#define INTERVAL     50

HDC hDC;

class CPress
{
private :

 int x0, y0, boxwidth, boxheight, Lwidth, Lheight, Rwidth, Rheight;
 double hL, hR, AL, AR, Velocity, Mass;

 void DrawDevice (int LineWidth=6)
 {

  HPEN Oldpen;
  Oldpen = (HPEN)SelectObject(hDC, NULL);

  // box
   // bottom
  MoveToEx(hDC, 0, y0, NULL);
  LineTo(hDC, x0 + boxwidth, y0);

  SelectObject(hDC, CreatePen(0, LineWidth, BLACK_PEN));
  MoveToEx(hDC, x0, y0, NULL);
  LineTo(hDC, x0 + boxwidth, y0);
   // ceil
  SelectObject(hDC, CreatePen(0, 1, BLACK_PEN));
  MoveToEx(hDC, 0, y0 + boxheight, NULL);
  LineTo(hDC, x0 + boxwidth - Rwidth , y0 + boxheight);

  SelectObject(hDC, CreatePen(0, LineWidth, BLACK_PEN));
  MoveToEx(hDC, x0 + Lwidth, y0 + boxheight, NULL);
  LineTo(hDC, x0 + boxwidth - Rwidth , y0 + boxheight);


  // left stack
   // leftwall
  SelectObject(hDC, CreatePen(0, 1, BLACK_PEN));
  MoveToEx(hDC, x0, 0, NULL);
  LineTo(hDC, x0, y0 + boxheight + Lheight);
  
  SelectObject(hDC, CreatePen(0, LineWidth, BLACK_PEN));
  MoveToEx(hDC, x0, y0, NULL);
  LineTo(hDC, x0, y0 + boxheight + Lheight);
   // rightwall
  SelectObject(hDC, CreatePen(0, 1, BLACK_PEN));
  MoveToEx(hDC, x0 + Lwidth, 0, NULL);
  LineTo(hDC, x0 + Lwidth, y0 + boxheight + Lheight);
  
  SelectObject(hDC, CreatePen(0, LineWidth, BLACK_PEN));
  MoveToEx(hDC, x0 + Lwidth, y0 + boxheight, NULL);
  LineTo(hDC, x0 + Lwidth, y0 + boxheight + Lheight);
   // ceil
  SelectObject(hDC, CreatePen(0, 1, BLACK_PEN));
  MoveToEx(hDC, 0, y0 + boxheight + Lheight, NULL);
  LineTo(hDC, x0 + Lwidth, y0 + boxheight + Lheight);

  SelectObject(hDC, CreatePen(0, LineWidth, BLACK_PEN));
  MoveToEx(hDC, x0, y0 + boxheight + Lheight, NULL);
  LineTo(hDC, x0 + Lwidth, y0 + boxheight + Lheight);


  // right stack
   // rightwall
  SelectObject(hDC, CreatePen(0, 1, BLACK_PEN));
  MoveToEx(hDC, x0 + boxwidth, 0, NULL);
  LineTo(hDC, x0 + boxwidth, y0 + boxheight + Rheight);
  
  SelectObject(hDC, CreatePen(0, LineWidth, BLACK_PEN));
  MoveToEx(hDC, x0 + boxwidth, y0, NULL);
  LineTo(hDC, x0 + boxwidth, y0 + boxheight + Rheight);
   // leftwall
  SelectObject(hDC, CreatePen(0, 1, BLACK_PEN));
  MoveToEx(hDC, x0 + boxwidth - Rwidth, 0, NULL);
  LineTo(hDC, x0 + boxwidth - Rwidth, y0 + boxheight + Rheight);
  
  SelectObject(hDC, CreatePen(0, LineWidth, BLACK_PEN));
  MoveToEx(hDC, x0 + boxwidth - Rwidth, y0 + boxheight, NULL);
  LineTo(hDC, x0 + boxwidth - Rwidth, y0 + boxheight + Rheight);
  /* // ceil
  SelectObject(hDC, CreatePen(0, 1, BLACK_PEN));
  MoveToEx(hDC, 0, y0 + boxheight + Rheight, NULL);
  LineTo(hDC, x0 + boxwidth, y0 + boxheight + Rheight);

  SelectObject(hDC, CreatePen(0, LineWidth, BLACK_PEN));
  MoveToEx(hDC, x0 + boxwidth - Rwidth, y0 + boxheight + Rheight, NULL);
  LineTo(hDC, x0 + boxwidth, y0 + boxheight + Rheight);
  */

  SelectObject(hDC, Oldpen);

 };
 void DrawWater ()
 {

  HBRUSH Oldbrush = (HBRUSH)SelectObject(hDC, NULL);
  HPEN OldPen = (HPEN)SelectObject(hDC, NULL);
  SelectObject(hDC, CreateSolidBrush(RGB(0,0,255)));
  SelectObject(hDC, CreatePen(PS_SOLID, 1, RGB(0,0,255)));

  Rectangle(hDC, x0, y0 + boxheight, x0 + boxwidth, y0);
  Rectangle(hDC, x0, y0 + boxheight + hL, x0 + Lwidth, y0 + boxheight);
  Rectangle(hDC, x0 + boxwidth - Rwidth, y0 + boxheight + hR, x0 + boxwidth, y0 + boxheight);

  SelectObject(hDC, OldPen);
  SelectObject(hDC, Oldbrush);

 };
 void DrawLoad (int Thickness=30)
 {

  HBRUSH Oldbrush = (HBRUSH)SelectObject(hDC, NULL);
  HBRUSH Oldpen = (HBRUSH)SelectObject(hDC, NULL);
  SelectObject(hDC, CreateSolidBrush(RGB(192,192,192)));
  SelectObject(hDC, CreatePen(PS_SOLID, 1, RGB(192,192,192)));

  Rectangle(hDC, x0, y0 + boxheight + hL + Thickness, x0 + Lwidth, y0 + boxheight + hL);
  Rectangle(hDC, x0 + boxwidth - Rwidth, y0 + boxheight + hR + Thickness, x0 + boxwidth, y0 + boxheight + hR);

  HDC MemDC = CreateCompatibleDC(hDC);
  HBITMAP MyBitmap = LoadBitmap(gInst, MAKEINTRESOURCE(IDB_BITMAP1));
  SelectObject(MemDC, MyBitmap);


  const int xCar = 450, yCar = 150;
  StretchBlt(hDC, x0 + boxwidth - (double)Rwidth/2.0 - xCar/2.0, y0 + boxheight + hR + Thickness + yCar, xCar, -yCar,
   MemDC, 0, 0, 333, 112, SRCCOPY);

  DeleteDC(MemDC);
  DeleteObject(MyBitmap);
  SelectObject(hDC, Oldbrush);
  SelectObject(hDC, Oldpen);
 };

public :

 CPress (int x0, int y0, int boxwidth, int boxheight, int Lwidth, int Lheight, int Rwidth, int Rheight, double Velocity, double Mass)
 {

  CPress::x0 = x0;
  CPress::y0 = y0;
  CPress::boxwidth = boxwidth;
  CPress::boxheight = boxheight;
  CPress::Lwidth = Lwidth;
  CPress::Lheight = Lheight;
  CPress::Rwidth = Rwidth;
  CPress::Rheight = Rheight;

  CPress::hL = Lheight;
  CPress::hR = 0;
  CPress::Velocity = Velocity;
  CPress::Mass = Mass;

  AL = pi* pow((double)Lwidth/2.0, 2.0);
  AR = pi* pow((double)Rwidth/2.0, 2.0);

 };
 void Move (int Interval)
 {

  double dt = (double)Interval / 1000;
  double vL, vR;


  if(hR < Rheight)
   vL = -Velocity,
   vR = Velocity* (AL/AR);
  else
   vL = 0,
   vR = 0;

  hL += vL* dt;
  hR += vR* dt;


  InvalidateRect(hWnd, NULL, TRUE);

 };
 void Draw ()
 {

  DrawWater();
  DrawDevice();
  DrawLoad();

  char Print [32];
  const double g = 9.80;

  sprintf(Print, "%.2lf N", Mass* g* (AL/AR));
  TextOutA(hDC, x0, y0 + boxheight + hL + 100, LPSTR(Print), strlen(Print));
  sprintf(Print, "%.2lf N", Mass* g);
  TextOutA(hDC, x0 + boxwidth - Rwidth, y0 + boxheight + hR + 250 , LPSTR(Print), strlen(Print));

 };

};


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

 PAINTSTRUCT ps;
 static CPress Press (/*x0, y0*/250, 200, /*box*/800, 200, /*left*/100, 700, /*right*/300, 78,
        /*velocity*/100, /*mass*/800 );
 
 switch(Message) {
 case WM_CREATE :
  return 0;

 case WM_PAINT :
  hDC = BeginPaint(hWnd, &ps);
  SetViewportOrgEx(hDC, 0, WndHeight, NULL);
  SetMapMode(hDC, MM_LOMETRIC);

  Press.Draw();

  EndPaint(hWnd, &ps);
  return 0;

 case WM_TIMER :
  Press.Move(INTERVAL);
  return 0;

 case WM_RBUTTONDOWN :
  SetTimer(hWnd, ID_TM_MAIN, INTERVAL, NULL);
  return 0;

 case WM_DESTROY :
  KillTimer(hWnd, ID_TM_MAIN);
  PostQuitMessage(0);
  return 0;
 }

 return DefWindowProc(hWnd, Message, wParam, lParam);
}