#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "lsctrl.h"

typedef struct {
  HWND frame ;
  HWND closebutton ;
  HBITMAP closebitmap ;
  HCURSOR hcurs ;
  HCURSOR vcurs ;
  int vertical ;
} CCWparams;

extern HINSTANCE hInstance ;
static char *szControlWindClassName = "ladSoftControlWindow" ;

void DrawMoveRect(HWND hwnd, RECT *r1)
{
   HDC dc = CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
   RECT r2 ;
   GetWindowRect(hwnd,&r2) ;
   r2.left += GetSystemMetrics(SM_CXDLGFRAME) ;
   r2.top += GetSystemMetrics(SM_CYDLGFRAME) + GetSystemMetrics(SM_CYMENU) +
               GetSystemMetrics(SM_CYCAPTION) ;
   r2.right = r1->right + r2.left ;
   r2.bottom = r1->bottom + r2.top ;
   r2.top += r1->top ;
   r2.left += r1->left ;
   DrawFocusRect(dc,&r2) ;
   DeleteDC(dc) ;
}
void DrawBorder(HDC dc, RECT *r1,int vertical)
{
   HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_INACTIVEBORDER)) ;
   RECT r2 ;
   r2 = *r1 ;
   if (vertical)
      r2.right = r2.left + 25 ;
   else
      r2.right = r2.left + 5 ;
   FillRect(dc,&r2,brush) ;
   r2 = *r1 ;
   r2.left = r2.right -5 ;
   FillRect(dc,&r2,brush) ;
   r2 = *r1 ;
   if (vertical)
      r2.bottom = r2.top + 5 ;
   else
      r2.bottom = r2.top + 25 ;
   FillRect(dc,&r2,brush) ;
   r2 = *r1 ;
   r2.top = r2.bottom - 5 ;
   FillRect(dc,&r2,brush) ;
   DeleteObject(brush) ;
}
LRESULT  CALLBACK _export ControlWindWndProc( HWND hwnd, UINT iMessage, WPARAM wParam,
                                                         LPARAM lParam )
{
   RECT r, *pr ;
   PAINTSTRUCT ps ;
   HDC dc ;
   CCWparams *ptr ;
   static int skip ;
   static int dragging,oncursor,sizing ;
   static RECT moverect ;
   static POINT movept ;
   static HCURSOR oldCursor ;
   POINT temppt ;
   HPEN pen1,pen2,pen3,oldpen ;                       
   int temp ;
   HBRUSH brush ;
   switch(iMessage) {
      case WM_NOTIFY:
      case WM_DRAWITEM:
         return SendMessage(GetParent(hwnd),iMessage,wParam, lParam) ;
      case WM_COMMAND:
         if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == 64371)
            SendMessage(GetParent(hwnd),WM_SYSCOMMAND,SC_CLOSE,0) ;
         else
            return SendMessage(GetParent(hwnd),iMessage,wParam,lParam) ;
         break ;
      case WM_CAPTURECHANGED:
         break ;
         break ;
      case WM_LBUTTONDOWN:
         movept.x = LOWORD(lParam) ;
         movept.y = HIWORD(lParam) ;
         ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
         if ((ptr->vertical && movept.x < 17) ||
               (!ptr->vertical && movept.y < 17))  {

            GetRelativeRect(ptr->frame, GetParent(hwnd), &moverect) ;
            SetCapture(hwnd) ;
            DrawMoveRect(ptr->frame,&moverect) ;
            dragging = TRUE ;
            skip = 1 ;
         } else if (oldCursor) {
            sizing = TRUE ;
            skip = 1 ;
            GetRelativeRect(ptr->frame, GetParent(hwnd), &moverect) ;
            SetCapture(hwnd) ;
            DrawMoveRect(ptr->frame,&moverect) ;
         }  
         GetWindowRect(ptr->frame,&r) ;
         ClipCursor(&r) ;
         break ;
      case WM_LBUTTONUP:
         ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
         if (dragging) {
            DrawMoveRect(ptr->frame,&moverect) ;
            dragging = FALSE ;
            ReleaseCapture() ;
            ClipCursor(0) ;
            SendMessage(GetParent(hwnd),WN_ENDMOVE, 0, (LPARAM) &moverect) ;
         } else if (sizing) {
            DrawMoveRect(ptr->frame,&moverect) ;
            ReleaseCapture() ;
            ClipCursor(0) ;
            InvalidateRect(GetParent(hwnd),0,FALSE) ;
            SendMessage(GetParent(hwnd),WN_ENDMOVE, 0, (LPARAM) &moverect) ;
            sizing = FALSE ;
         }
         break ;
      case WM_MOUSEMOVE:
         ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
         if (dragging) {
            if (skip) {
               skip-- ;
               break ;
            }
            DrawMoveRect(ptr->frame,&moverect) ;
            moverect.left += (long)(short)LOWORD(lParam) - movept.x ;
            moverect.right += (long)(short)LOWORD(lParam) - movept.x ;
            moverect.top += (long)(short)HIWORD(lParam) - movept.y ;
            moverect.bottom += (long)(short)HIWORD(lParam) - movept.y ;
            movept.x = (long)(short)LOWORD(lParam) ;
            movept.y = (long)(short)HIWORD(lParam) ;
            SendMessage(GetParent(hwnd),WM_MOVING,0,(LPARAM)&moverect) ;
            DrawMoveRect(ptr->frame,&moverect) ;
         } else if (sizing) {
            DrawMoveRect(ptr->frame,&moverect) ;
            switch(oncursor) {
               case HTLEFT:
                  moverect.left += (long)(short)LOWORD(lParam) - movept.x ;
                  temp = WMSZ_LEFT ;
                  break ;
               case HTTOP:
                  moverect.top += (long)(short)HIWORD(lParam) - movept.y ;
                  temp = WMSZ_TOP ;
                  break ;
               case HTRIGHT:
                  moverect.right += (long)(short)LOWORD(lParam) - movept.x ;
                  temp = WMSZ_RIGHT ;
                  break ;
               case HTBOTTOM:
                  moverect.bottom += (long)(short)HIWORD(lParam) - movept.y ;
                  temp = WMSZ_BOTTOM ;
                  break ;
            }
            movept.x = (long)(short)LOWORD(lParam) ;
            movept.y = (long)(short)HIWORD(lParam) ;
            SendMessage(GetParent(hwnd),WM_SIZING,temp,(LPARAM)&moverect) ;
            DrawMoveRect(ptr->frame,&moverect) ;
         }  else {
            ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
            GetClientRect(hwnd,&r) ;
            if (LOWORD(lParam) <= r.right-1 && LOWORD(lParam) >= r.right-3) {
               if (!oldCursor)
                  oldCursor = SetCursor(ptr->hcurs) ;
               oncursor = HTRIGHT ;
            } else if (HIWORD(lParam) <= r.bottom -1 && HIWORD(lParam) >= r.bottom-3) {
               if (!oldCursor)
                  oldCursor = SetCursor(ptr->vcurs) ;
               oncursor = HTBOTTOM ;
            } else if (LOWORD(lParam) <= 3) {
               if (!oldCursor)
                  oldCursor = SetCursor(ptr->hcurs) ;
               oncursor = HTLEFT ;
            } else if (HIWORD(lParam) <= 3) {
               if (!oldCursor)
                  oldCursor = SetCursor(ptr->vcurs) ;
               oncursor = HTTOP ;
            } else if (oldCursor) {
               SetCursor(oldCursor) ;
               oldCursor = 0 ;
               oncursor = 0 ;
            }
            
         }

         break ;
      case WM_ERASEBKGND:
         return 0 ;
      case WM_PAINT:
         ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
         dc = BeginPaint(hwnd, &ps) ;
         GetClientRect(hwnd,&r) ;
         DrawBorder(dc,&r,ptr->vertical) ;
         
         pen1 = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT)) ;
         pen2 = CreatePen(PS_SOLID, 2, GetSysColor(COLOR_3DFACE)) ;
         pen3 = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW)) ;
         brush = CreateSolidBrush(COLOR_INACTIVECAPTION) ;
         if (!ptr->vertical) {
            r = ps.rcPaint ;
            r.top = 5 ;
            r.bottom = 17 ;
            r.left+=5 ;
            r.right-=5 ;
            FillRect(dc,&r,brush) ;
            oldpen = SelectObject(dc,pen1) ;
            MoveToEx(dc,r.left + 4,r.top+3,0) ;
            LineTo(dc,r.right - 16, r.top+3) ;
            SelectObject(dc,pen2) ;
            MoveToEx(dc,r.left + 4,r.top+4,0) ;
            LineTo(dc,r.right - 16, r.top+4) ;
            SelectObject(dc,pen3) ;
            MoveToEx(dc,r.left + 4,r.top+6,0) ;
            LineTo(dc,r.right - 16, r.top+6) ;
            SelectObject(dc,pen1) ;
            MoveToEx(dc,r.left + 4,r.top+7,0) ;
            LineTo(dc,r.right - 16, r.top+7) ;
            SelectObject(dc,pen2) ;
            MoveToEx(dc,r.left + 4,r.top+8,0) ;
            LineTo(dc,r.right - 16, r.top+8) ;
            SelectObject(dc,pen3) ;
            MoveToEx(dc,r.left + 4,r.top+10,0) ;
            LineTo(dc,r.right - 16, r.top+10) ;
         } else {
            r = ps.rcPaint ;
            r.left = 5 ;
            r.right = 17 ;
            r.top += 5 ;
            r.bottom-=5 ;
            FillRect(dc,&r,brush) ;
            oldpen = SelectObject(dc,pen1) ;
            MoveToEx(dc,r.left+3,r.top+16,0) ;
            LineTo(dc,r.left+3,r.bottom-4) ;
            SelectObject(dc,pen2) ;
            MoveToEx(dc,r.left+4,r.top+16,0) ;
            LineTo(dc,r.left+4,r.bottom-4) ;
            SelectObject(dc,pen3) ;
            MoveToEx(dc,r.left+6,r.top+16,0) ;
            LineTo(dc,r.left+6,r.bottom-4) ;
            SelectObject(dc,pen1) ;
            MoveToEx(dc,r.left+7,r.top+16,0) ;
            LineTo(dc,r.left+7,r.bottom-4) ;
            SelectObject(dc,pen2) ;
            MoveToEx(dc,r.left+7,r.top+16,0) ;
            LineTo(dc,r.left+7,r.bottom-4) ;
            SelectObject(dc,pen3) ;
            MoveToEx(dc,r.left+10,r.top+16,0) ;
            LineTo(dc,r.left+10,r.bottom-4) ;
         }                    
         SelectObject(dc, oldpen) ;
         DeleteObject(brush) ;
         DeleteObject(pen1) ;
         DeleteObject(pen2) ;
         DeleteObject(pen3) ;
         EndPaint(hwnd, &ps) ;
         break ;
		case WM_CREATE :
         dragging = 0 ;
         ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CCWparams)) ;
         SetWindowLong(hwnd,0,(DWORD)ptr) ;
         GetClientRect(hwnd,&r) ;
         ptr->closebutton = CreateWindow("BUTTON","",
                     WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_BITMAP,
                     r.right >r.bottom ? r.right-17 : 6,6,10,10,hwnd,(HMENU)64371,(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),0) ;
         ptr->closebitmap = LoadBitmap(hInstance,"ID_CLOSEBMP") ;
         ptr->vertical = FALSE ;
         ptr->hcurs = LoadCursor(hInstance,"ID_SIZEHCUR") ;
         ptr->vcurs = LoadCursor(hInstance,"ID_SIZEVCUR") ;
         SendMessage(ptr->closebutton,BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)ptr->closebitmap) ;
			return 0 ;
		case WM_DESTROY:
         ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
         DestroyWindow(ptr->closebutton) ;
         DeleteObject(ptr->closebitmap) ;
         DeleteObject(ptr->hcurs) ;
         DeleteObject(ptr->vcurs) ;
         HeapFree(GetProcessHeap(),0,ptr) ;
         dragging = 0 ;
         break ;
		case WM_CLOSE:

         return 0 ;
      case LCF_ADJUSTRECT:
         ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
         pr = (RECT *)lParam ;
         if (ptr->vertical) {
            pr->left += temp = 5 ;
            pr->right -= temp ;
            pr->top += temp ;
            pr->bottom-= temp ;
            pr->left += 15 ;
         } else {
            pr->left += temp = 5 ;
            pr->right -= temp ;
            pr->top += temp = 5 ;
            pr->bottom -= temp ;
            pr->top += 15 ;

         }
         return 0 ;
      case LCF_SETFRAME:
         ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
         ptr->frame = (HWND)lParam ;
         ptr->vertical = wParam ;
         break ;
      case WM_SIZE :
         ptr = (CCWparams *)GetWindowLong(hwnd,0) ;
         if (ptr->vertical)
            MoveWindow(ptr->closebutton,6,6,10,10,0 );
         else
            MoveWindow(ptr->closebutton,LOWORD(lParam)-17,6,10,10, 0) ;
         break ;
	}
   return DefWindowProc(hwnd, iMessage, wParam, lParam) ;
}

void RegisterControlWindow(void)
{
		WNDCLASS wc ;
      wc.style = 0 ;
      wc.lpfnWndProc = &ControlWindWndProc ;
		wc.cbClsExtra = 0;
      wc.cbWndExtra = sizeof(LPVOID);
		wc.hInstance = hInstance ;
		wc.hIcon = LoadIcon(0,IDI_APPLICATION) ;
      wc.hCursor = 0;
      wc.hbrBackground =  GetStockObject(WHITE_BRUSH) ;
		wc.lpszMenuName = 0 ;
      wc.lpszClassName = szControlWindClassName ;
		RegisterClass(&wc) ;

}
HWND CreateControlWindow(HWND frame, HWND parent, RECT *r, int vertical)
{
   HWND hwnd = CreateWindowEx(0, szControlWindClassName, "",
            WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD,
            r->left,r->right-r->left,r->top,r->bottom, 
            parent, (HMENU)0 ,(HINSTANCE)GetWindowLong(parent,GWL_HINSTANCE), 0) ;

   if (hwnd)
      SendMessage(hwnd,LCF_SETFRAME,vertical,(LPARAM)frame) ;
   return hwnd ;   
}