/* mouscurs.cpp   change mouse cursor shape and move the caret */

#include <windows.h>
#include "resource.h"

LRESULT CALLBACK WndProc (HWND hWnd, UINT wMessage,
                                   WPARAM wParam, LPARAM lParam);

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
                                                LPSTR lpszCmdLine, int nCmdShow)
{
    HWND        hWnd ;      /* the window's "handle" */
    MSG         msg ;       /* a message structure */
    WNDCLASS    wndclass ;  /* window class structure */

        wndclass.style          = CS_HREDRAW | CS_VREDRAW ;
        wndclass.lpfnWndProc    = WndProc ;
        wndclass.cbClsExtra     = 0 ;
        wndclass.cbWndExtra     = 0 ;
        wndclass.hInstance      = hInstance ;
        wndclass.hIcon          = NULL ;
                /* note that no cursor is defined for the class */
        wndclass.hCursor        = NULL ;
        wndclass.hbrBackground  = GetStockObject (WHITE_BRUSH) ;
        wndclass.lpszMenuName   = "MYMENU" ;
        wndclass.lpszClassName  = "MyClass" ;
        if (!RegisterClass (&wndclass))
            return 0 ;

    hWnd = CreateWindow ("MyClass","Mouse Cursor App", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL) ;
    ShowWindow (hWnd, nCmdShow) ;   /* display the window */
    UpdateWindow (hWnd) ;

    while (GetMessage (&msg, NULL, 0, 0))   /* message loop */
    {
        TranslateMessage (&msg) ;   /* translate keyboard messages */
        DispatchMessage (&msg) ;    /* send message to WndProc() */
    }
    return (msg.wParam) ;
}

LRESULT CALLBACK WndProc (HWND hWnd, UINT wMessage,
                                   WPARAM wParam, LPARAM lParam)
{
    static HCURSOR  hCursor ;
    HANDLE          hInstance ;
    int             nBorderWide, nCaptionTall ;
    static  int     nXpos = 0, nYpos = 0 ;

    switch (wMessage)       /* process windows messages */
    {
        case WM_CREATE:     /* program just starting */
                            /* start with the arrow cursor shape */
            hCursor = LoadCursor (NULL, IDC_ARROW) ;
            break ;
        case WM_COMMAND:
            switch (LOWORD(wParam))         /* menu items */
            {                       /* load selected cursor shape */
                case IDM_ARROW:         /* first two are stock cursors */
                    hCursor = LoadCursor (NULL, IDC_ARROW) ;
                    break ;
                case IDM_CROSS:
                    hCursor = LoadCursor (NULL, IDC_CROSS) ;
                    break ;
                case IDM_HAND:          /* second two are loaded from resources */                                
                    hInstance = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE) ;
                    hCursor = LoadCursor (hInstance, "HAND") ;
                    break ;
                case IDM_MOUSE:
                    hInstance = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE) ;
                    hCursor = LoadCursor (hInstance, "MOUSE") ;
                    break ;
                case IDM_QUIT:
                    DestroyWindow (hWnd) ;  /* destroy window, */
                    break ;         /* terminating application */
            }
            break ;

        case WM_SETCURSOR:          /* mouse moved into client area, so */
            SetCursor (hCursor) ;   /* change the cursor shape */
            break ;                 /* to the last one loaded */

        case WM_LBUTTONDOWN:        /* move caret to new position */
            nXpos = LOWORD (lParam) ;   /* save X,Y position */
            nYpos = HIWORD (lParam) ;
            SetCaretPos (nXpos, nYpos) ;
            break ;

        case WM_SETFOCUS:   /* window gaining input focus */
                            /* create the window's caret */
                            /* base caret width on window border width */
            nBorderWide = GetSystemMetrics (SM_CXBORDER) ;
                            /* base caret height on caption height */
            nCaptionTall = GetSystemMetrics (SM_CYCAPTION) ;
            CreateCaret (hWnd, NULL, nBorderWide, nCaptionTall) ;
                            /* put caret back at last X,Y location */
            SetCaretPos (nXpos, nYpos) ;
                ShowCaret (hWnd) ;      /* show caret */
            break ;
        case WM_KILLFOCUS:          /* window losing input focus */
            DestroyCaret () ;       /* destroy caret for now */
            break ;

        case WM_DESTROY:    /* stop application */
            PostQuitMessage (0) ;
            break ;

        default:        /* default windows message processing */
            return DefWindowProc (hWnd, wMessage, wParam, lParam) ;
    }
    return (0) ;
}