/******************************************************************************\
*
*  PROGRAM:     SPINTEST.C
*
*  PURPOSE:     Demonstrates the use of the SPINCUBE custom control.
*
*  FUNCTIONS:   WinMain        - standard stuff; also loads the
*                                  SPINCUBE.DLL and creates a couple
*                                  of spincube controls.
*               MainWndProc    - generic window procedure.
*               SpintestDlgProc- generic dialog procedure.
*               AboutDlgProc   - processes about dialog messages
*
*                           Microsoft Developer Support
*                  Copyright (c) 1992-1996 Microsoft Corporation
*
\******************************************************************************/

#include <windows.h>
#include <stdio.h>
#include "spintest.h"

//
// The exported variables from SPINCUBE.C.
//
//   Although pointers to these vars are actually exported,
//    the compiler will take care of that for us.
//

extern int __declspec(dllimport) giNumSpincubesThisProcess;
extern int __declspec(dllimport) giNumSpincubesAllProcesses;


//
// function prototype for looking up string resources
//

LPTSTR GetStringRes (int);


/******************************************************************************\
*
*  FUNCTION:    WinMain (standard WinMain INPUTS/RETURNS)
*
\******************************************************************************/

int WINAPI WinMain (HANDLE hInstance,HANDLE hPrevInstance, LPSTR lpCmdLine,
                   int     nCmdShow)
{
  WNDCLASS wc;
  HWND   hwnd;
  MSG    msg;
  RECT   rect;
  WORD   i;

  wc.style         = 0;
  wc.lpfnWndProc   = (WNDPROC) MainWndProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.hInstance     = hInstance;
  wc.hIcon         = LoadIcon (hInstance, "spintesticon");
  wc.hCursor       = LoadCursor (NULL, IDC_ARROW);
  wc.hbrBackground = GetStockObject (WHITE_BRUSH);
  wc.lpszMenuName  = (LPSTR) "Menu";
  wc.lpszClassName = (LPSTR) "Main";

  if (!RegisterClass (&wc))
  {
    MessageBox (NULL,
                GetStringRes (IDS_REGCLASSFAIL),
                "SPINTEST", MB_OK | MB_ICONEXCLAMATION);
    return(FALSE);
  }

  ghInst = hInstance;
  if (!(hwnd = CreateWindow ("Main",
                             GetStringRes (IDS_WINDOWTITLE),
                             WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT, CW_USEDEFAULT,
                             CW_USEDEFAULT, CW_USEDEFAULT,
                             NULL, NULL, ghInst, NULL)))
    return 0;


  //
  // Create a couple of SpinCube custom controls, we'll size them later in
  //   the WM_SIZE message handler
  //

  for (i = 0; i < 4; i++)

    gahwndSpin[i] = CreateWindow ("Spincube", "",
                                  WS_VISIBLE | WS_CHILD |
                                  SS_INMOTION | SS_ERASE,
                                  0, 0, 0, 0, hwnd, NULL, NULL, NULL);


  //
  // Delete the SS_ERASE to the 1st & 4th controls so we get the
  //   trailing cubes effect.
  //

  SetWindowLong (gahwndSpin[0], GWL_STYLE,
                 GetWindowLong (gahwndSpin[0], GWL_STYLE) & ~ SS_ERASE);
  SetWindowLong (gahwndSpin[3], GWL_STYLE,
                 GetWindowLong (gahwndSpin[3], GWL_STYLE) & ~ SS_ERASE);


  //
  // Send ourself a WM_SIZE so the controls will get sized appropriately
  //

  GetClientRect (hwnd, &rect);
  SendMessage (hwnd, WM_SIZE, 0,
               MAKELONG((WORD)rect.right,(WORD)rect.bottom));

  ShowWindow (hwnd, nCmdShow);

  while (GetMessage (&msg, NULL, 0, 0))
  {
    TranslateMessage (&msg);
    DispatchMessage  (&msg);
  }

  return (msg.wParam);
}



/******************************************************************************\
*
*  FUNCTION:    MainWndProc (standard window procedure INPUTS/RETURNS)
*
\******************************************************************************/

LRESULT CALLBACK MainWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
    case WM_COMMAND:

      switch (LOWORD(wParam))
      {
        case IDM_DLGEDITDIALOG:

          DialogBox (ghInst, (LPCTSTR) "SpintestDlg", hwnd, (DLGPROC) DlgProc);
          break;

        case IDM_SPINTESTSTATS:

          DialogBox (ghInst, (LPCTSTR) "Stats", hwnd, (DLGPROC) DlgProc);
          break;

        case IDM_ABOUT:

          DialogBox (ghInst, (LPCTSTR)"About", hwnd, (DLGPROC) DlgProc);
          break;

      }
      break;

    case WM_SIZE:
    {
      //
      // Resize the controls such that each cover half the client area
      //   (plus a little border).
      //

      int width  = (int) LOWORD(lParam);
      int height = (int) HIWORD(lParam);

      SetWindowPos (gahwndSpin[0], NULL,
                    BORDER, BORDER,
                    width/2 - BORDER, height/2 - BORDER,
                    SWP_SHOWWINDOW);
      SetWindowPos (gahwndSpin[1], NULL,
                    width/2 + BORDER, BORDER,
                    width/2 - 2*BORDER, height/2 - BORDER,
                    SWP_SHOWWINDOW);
      SetWindowPos (gahwndSpin[2], NULL,
                    BORDER, height/2 + BORDER,
                    width/2 - BORDER, height/2 - 2*BORDER,
                    SWP_SHOWWINDOW);
      SetWindowPos (gahwndSpin[3], NULL,
                    width/2 + BORDER, height/2 + BORDER,
                    width/2 - 2*BORDER, height/2 - 2*BORDER,
                    SWP_SHOWWINDOW);
      break;
    }

    case WM_DESTROY:

      PostQuitMessage (0);
      break;

    default:

      return (DefWindowProc (hwnd, msg, wParam, lParam));
  }
  return 0;
}



/******************************************************************************\
*
*  FUNCTION:    DlgProc (standard dialog procedure INPUTS/RETURNS)
*
*  COMMENTS:    Our common dlg proc (why have 3 that do the same thing???)
*
\******************************************************************************/

LRESULT CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message)
  {
    case WM_INITDIALOG:

      //
      // If this dlg the "Stats" dlg fill in the appropriate fields.
      //   If not these calls will just fail.
      //
      // If the references to the giNum* vars are commented out &
      //   the program gets rebuilt don't be surprised if no spincubes
      //   appear- since no references to spincube.lib the linker will
      //   infer that it is not needed, & will not cause it to get
      //   loaded. You'll need to make a call to LoadLibrary ("SPINCUBE.DLL")
      //   prior to calling CreateWindow ("SPINCUBE"...).
      //

      SetDlgItemInt (hwnd, 500, giNumSpincubesThisProcess, TRUE);
      SetDlgItemInt (hwnd, 501, giNumSpincubesAllProcesses, TRUE);
      return (TRUE);

    case WM_COMMAND:

      if (LOWORD(wParam) == IDOK)

        EndDialog (hwnd, TRUE);

      return (TRUE);
  }
  return (FALSE);
}



/******************************************************************************\
*
*  FUNCTION:    GetStringRes (int id INPUT ONLY)
*
*  COMMENTS:    Load the resource string with the ID given, and return a
*               pointer to it.  Notice that the buffer is common memory so
*               the string must be used before this call is made a second time.
*
\******************************************************************************/

LPTSTR   GetStringRes (int id)
{
  static TCHAR buffer[MAX_PATH];

  buffer[0]=0;
  LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
  return buffer;
}
