/* ----------------------------- OWNER.C -----------------------------
 *      Gestione della finestra di dialogo
 * ---------------------------------------------------------------- */

#define STRICT

#include <Windows.h>
#include "dlg3.h"

// ---- Variabili globali al sorgente
typedef struct
{
	COLORREF                crColore;
	int                     itemWidth,
				itemHeight;
} MIOITEM;
typedef MIOITEM FAR *LPMIOITEM;

MIOITEM                 ListaItems [] =
{
	{RGB(0, 0, 0), 18, 8},
	{RGB(0, 0, 255), 20, 10},
	{RGB(0, 255, 0), 22, 12},
	{RGB(0, 255, 255), 24, 14},
	{RGB(255, 0, 0), 26, 16},
	{RGB(255, 0, 255), 28, 18},
	{RGB(255, 255, 0), 30, 20},
	{RGB(255, 255, 255), 32, 22}
};

static LPVARIABLES      lpVar;

// ---- Per la sotto-clasificazione
FARPROC        lpOldProc;             // Vecchia WndProc Edit

/* -------------------------- EditWndProc -----------------------------
 *      WndProc sotto classificata dell'edit
 *              Controllo elementare di numericit…
 * ---------------------------------------------------------------- */

LRESULT FAR PASCAL EditWndProc (HWND hWnd, WORD wMsg, WORD wParam, 
				LONG lParam)
{
LRESULT          lRes = 0;               // Valore di ritorno
BOOL             bElabora = TRUE;        // Indica comando elaborato

	switch (wMsg)
	{
	case WM_CHAR:
		if ((wParam < '0' || wParam > '9') && wParam != 0x08)
			MessageBeep (0);      // Tasto rifiutato
		else
			bElabora = FALSE;

		break;

	default:
		bElabora = FALSE;
		break;
	}

// ---- Elaborazione di default
	if (!bElabora)
		lRes = CallWindowProc ((WNDPROC)lpOldProc, hWnd, wMsg, 
					wParam, lParam);

	return lRes;
}

/* -------------------------- InitSottoClass -------------------------
 *      Definisce la sotto classificazione
 * ---------------------------------------------------------------- */

static VOID InitSottoClass (HWND hWnd)
{
HWND            hWndEdit;
FARPROC         lpNewProc;                      // Nuova WndProc Edit

	hWndEdit = GetDlgItem (hWnd, IDD_EDIT);
	lpNewProc = MakeProcInstance ((FARPROC)EditWndProc, hInst);
	lpOldProc = (FARPROC)SetWindowLong (hWndEdit, GWL_WNDPROC,
										(long)lpNewProc);
}

/* -------------------------- ConcSottoClass -------------------------
 *      Conclude la sotto-classificazione ripulendo
 * ---------------------------------------------------------------- */

static VOID ConcSottoClass (HWND hWnd)
{
HWND         hWndEdit;
FARPROC      lpNewProc;           // Nuova WndProc Edit

	hWndEdit = GetDlgItem (hWnd, IDD_EDIT);
	lpNewProc = (FARPROC)SetWindowLong (hWndEdit, GWL_WNDPROC,
										(long)lpOldProc);
	FreeProcInstance (lpNewProc);
}

/* -------------------------- wmCommand -----------------------------
 *      Elabora il messaggio WM_COMMAND
 * id      = wParam                  E' l'identificatore.
 * hCtl    = (HWND) LOWORD (lParam)  Identifica il controllo che
 *                                   invia il messaggio, se non 
 *                                   proviene da un controllo questo
 *                                   parametro Š uguale a 0.    
 * nNotify = HIWORD (lParam)         Messaggio di notifica, se il   
 *                                   msg. proviene da un acceleratore
 *                                   questo parametro Š uguale a 1   
 *                                   se da un menu Š uguale a 0.
 * ---------------------------------------------------------------- */

static VOID wmCommand (HWND hWnd, int id, HWND hCtl, int nNotify)
{
BOOL         bTrans;
DWORD        dwPos;

	switch (id)
	{
	case IDD_EDIT:
		if (nNotify == EN_CHANGE)
			EnableWindow (GetDlgItem (hWnd, IDOK),
				GetWindowTextLength (GetDlgItem (hWnd, 
						     IDD_EDIT)));
		break;

	case IDOK:
// ---- Recupera i valori inseriti
		lpVar->nNumero =
			GetDlgItemInt (hWnd, IDD_EDIT, &bTrans, FALSE);
		lpVar->iColoreLB =
			(int)SendDlgItemMessage (hWnd, IDD_LISTBOX, 
						 LB_GETCURSEL, 0, 0L);
		lpVar->iColoreCB =
			(int)SendDlgItemMessage (hWnd, IDD_COMBOBOX, 
						 CB_GETCURSEL, 0, 0L);

		dwPos = SendDlgItemMessage (hWnd, IDD_BERSAGLIO, BER_GETPOS, 
					    0, 0L);
		lpVar->xBersaglio = LOWORD (dwPos);
		lpVar->yBersaglio = HIWORD (dwPos);

// ---- E conclude
		ConcSottoClass (hWnd);
		EndDialog (hWnd, TRUE);
		break;

	case IDCANCEL:
		ConcSottoClass (hWnd);
		EndDialog (hWnd, TRUE);
		break;

	default:
		break;
	}

	return;
}

/* -------------------------- wmInitDialog --------------------------
 *      Elabora il messaggio WM_INITDIALOG
 * idFocus = (HWND) wParam    Handle del controllo che pu• ricevere 
 *                            il focus.
 * lParam                     Contiene dati specifici dell'applica_
 *                            zione.
 * Il valore di ritorno Š TRUE normalmente, o FALSE se il focus 
 * Š stato messo su un controllo.
 * ---------------------------------------------------------------- */

static BOOL wmInitDialog (HWND hWnd, int idFocus, DWORD lParam)
{
register        i;
LPMIOITEM       lpItem;

// ---- Blocco di variabili
	lpVar = (LPVARIABLES)lParam;

// ---- Riempie la lista
	for (i = 0; i < 8; ++i)
	{
		lpItem = &ListaItems[i];
		SendDlgItemMessage (hWnd, IDD_LISTBOX, LB_ADDSTRING, 0,
				    (long)lpItem);
		SendDlgItemMessage (hWnd, IDD_COMBOBOX, CB_ADDSTRING, 0,
				    (long)lpItem);
	}

// ---- E mette i valori di default
	SendDlgItemMessage (hWnd, IDD_LISTBOX, LB_SETCURSEL,
			    lpVar->iColoreLB, 0L);
	SendDlgItemMessage (hWnd, IDD_COMBOBOX, CB_SETCURSEL,
			    lpVar->iColoreCB, 0L);


// ---- Inizializza l'edit, 5 caratteri max
	SendDlgItemMessage (hWnd, IDD_EDIT, EM_LIMITTEXT, 5, 0L);
	SetDlgItemInt (hWnd, IDD_EDIT, lpVar->nNumero, FALSE);

// ---- La sotto-classe
	InitSottoClass (hWnd);

// ---- Inizializza il bersaglio
	SendDlgItemMessage (hWnd, IDD_BERSAGLIO, BER_SETPOS, 0,
			    MAKELONG (lpVar->xBersaglio, lpVar->yBersaglio));

	return TRUE;
}

/* -------------------------- wmCtlColor ----------------------------
 *      Elabora il messaggio WM_CTLCOLOR
 * hDC   = (HDC) wParam             E' il DC del controllo.
 * hCtl  = (HWND) LOWORD (lParam)   Handle del controllo.
 * nCode = (int) HIWORD (lParam)    Tipo di controllo.
 * Restituisce un handle al pennello da usare per dipingere lo 
 * sfondo del controllo oppure NULL.
 * ---------------------------------------------------------------- */

static HBRUSH wmCtlColor (HWND hWnd, HDC hDC, HWND hCtl, int nCode)
{
HBRUSH          hBr = NULL;
RECT            Rect;

// ---- Static UserItem
	if (hCtl == GetDlgItem (hWnd, IDD_STATIC))
	{

		GetClientRect (hCtl, &Rect);
		hBr = GetStockObject (GRAY_BRUSH);
		FillRect (hDC, &Rect, hBr);
		Ellipse (hDC, Rect.left, Rect.top, Rect.right, Rect.bottom);
	}

	return hBr;
}

/* -------------------------- wmMeasureItem -------------------------
 *      Elabora il messaggio WM_MEASUREITEM
 * lpMIS = (MEASUREITEMSTRUCT FAR*) lParam   Punta ad una struttura 
 *                                           MEASUREITEMSTRUCT.
 * ---------------------------------------------------------------- */

static VOID wmMeasureItem (HWND hWnd, MEASUREITEMSTRUCT FAR* lpMIS)
{
	if (lpMIS->CtlID == IDD_LISTBOX)
	{                                // List box, fixed
		lpMIS->itemWidth = 20;
		lpMIS->itemHeight = 16;
	}

	else
	{                                // Combo box, variable
		if (lpMIS->itemID == -1)
		{                        // Controllo edit, dim max
			lpMIS->itemWidth = 32;
			lpMIS->itemHeight = 22;
		}
		else
		{                        // Item
	    lpMIS->itemWidth = ((LPMIOITEM)(lpMIS->itemData))->itemWidth;
	    lpMIS->itemHeight = ((LPMIOITEM)(lpMIS->itemData))->itemHeight;
		}
	}
	return;
}

/* -------------------------- wmDrawItem ----------------------------
 *      Elabora il messaggio WM_DRAWITEM
 * lpDIS = (DRAWITEMSTRUCT FAR*) lParam    Punta ad una struttura 
 *                                         DRAWITEMSTRUCT.
 * ---------------------------------------------------------------- */

static VOID wmDrawItem (HWND hWnd, DRAWITEMSTRUCT FAR* lpDIS)
{
HBRUSH        hBrush;

// ---- Disegna l'elemento
	if (lpDIS->itemID != -1)
	{                             // Salvo controllo edit
	hBrush = CreateSolidBrush (((LPMIOITEM)(lpDIS->itemData))->crColore);
		FillRect (lpDIS->hDC, &lpDIS->rcItem, hBrush);
		DeleteObject (hBrush);

// ---- Disegna la selezione
		if (lpDIS->itemState & ODS_SELECTED)
			FrameRect (lpDIS->hDC, &lpDIS->rcItem, 
				   GetStockObject (BLACK_BRUSH));
	}

	return;
}

/* -------------------------- OwnerDlgProc ----------------------------
 *      DlgProc della finestra di dialogo
 * ---------------------------------------------------------------- */

BOOL FAR PASCAL OwnerDlgProc (HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
{
BOOL        bRes = TRUE;            // Valore di ritorno

	switch (wMsg)
	{
	case WM_COMMAND:
		wmCommand (hWnd, LOWORD (wParam), (HWND) lParam,
			   HIWORD (wParam));
		break;

	case WM_INITDIALOG:
		bRes = wmInitDialog (hWnd, wParam, lParam);
		break;

  //	case WM_CTLCOLOR:
  case WM_CTLCOLORBTN:
  case WM_CTLCOLORDLG:
  case WM_CTLCOLOREDIT:
  case WM_CTLCOLORLISTBOX:
  case WM_CTLCOLORMSGBOX:
  case WM_CTLCOLORSCROLLBAR:
  case WM_CTLCOLORSTATIC:
  		bRes = (BOOL)wmCtlColor (hWnd, (HDC)wParam,
  					 (HWND)LOWORD (lParam),
  					 (int)HIWORD (lParam));
  		break;

	case WM_MEASUREITEM:
		wmMeasureItem (hWnd, (MEASUREITEMSTRUCT FAR*)lParam);
		break;

	case WM_DRAWITEM:
		wmDrawItem (hWnd, (DRAWITEMSTRUCT FAR*)lParam);
		break;

	default:
		bRes = FALSE;
		break;
	}

	return bRes;
}