COLORS.C

/************************************************************************ 

File: colors.c

Purpose:

This file contains all the code necessary for the colors dialog.


Functions:

DoColorsDialog() -- Starts off the creation of the main colors dlg

ColorsProc() -- Callback function for the colors dialog

InitColorStruct() -- Initializes default CHOOSECOLOR strucure

FillColorDlg() -- Fills the colors dialog with the current
CHOOSECOLOR structure values.

GetColorDlg() -- Retrieves users edits and puts them in
the appropriate CHOOSECOLOR structure.

ColorsHookProc() -- Callback hook function if the ChooseColor()
function is called with CC_ENABLEHOOK

GetColorsResHandle() -- Loads a custom template from the EXE
and returns a handle to it

DoChooseColorStuff() -- Calls the ChooseColor() function.

ColorThreadProc1() -- Starting address for the first thread

ColorThreadProc2() -- Starting address for the second thread

MultiThreadColorDlg() -- Creates two threads in this process
which each create ChooseColor() dialogs.

EnableColorButtons() -- Enables or disables buttons in the colors
dialog. Necessary for the multithreading.


************************************************************************/


#include <windows.h>
#include <commdlg.h>
#include <stdlib.h>
#include <winnls.h>
#include "cdtest.h"
#include "colors.h"


/* Function prototypes */
void InitColorStruct(HWND hwnd, LPCHOOSECOLOR) ;
void FillColorDlg(HWND hwnd, LPCHOOSECOLOR) ;
void GetColorDlg(HWND hwnd, LPCHOOSECOLOR) ;
void DoChooseColorStuff(HWND, LPCHOOSECOLOR) ;
UINT APIENTRY ColorsHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam) ;


/* Variables and external declarations */

CHOOSECOLOR cc ;
DWORD dwCustColors[16] ;
DWORD dwColor ;
HANDLE hDialogColors, hResColors ;
HANDLE GetColorsResHandle(void) ;
TCHAR szTemplateNameC[50] ;
extern UINT uMode ;
extern LONG MyAtol(LPTSTR, BOOL, LPBOOL) ;


/* Multithreading stuff */

DWORD dwColorThreadID1 ;
DWORD dwColorThreadID2 ;
DWORD dwColorThreadParm1 ;
DWORD dwColorThreadParm2 ;
DWORD ColorThreadProc1(LPDWORD) ;
DWORD ColorThreadProc2(LPDWORD) ;
void MultiThreadColorDlg(void) ;
void EnableColorButtons(HWND, BOOL) ;
HANDLE hColorThread1 ;
HANDLE hColorThread2 ;
HWND hwndMainColor ;
int nOpenColorDlgCount ;
CHOOSECOLOR ccThread1 ;
CHOOSECOLOR ccThread2 ;




/************************************************************************

Function: DoColorsDialog(HWND)

Purpose: To create the ChooseColor() common dialog creation dialog.

Returns: Nothing.

Comments:

************************************************************************/

void DoColorsDialog(HWND hwnd)
{


DialogBox(hInst, MAKEINTRESOURCE(ID_COLORSDIALOG),
hwnd, ColorsProc) ;

}







/************************************************************************

Function: ColorsProc(HWND, UINT, UINT, LONG)

Purpose: The callback function for the main colors dialog.

Returns: TRUE or FALSE depending on the situation.

Comments:

************************************************************************/


BOOL APIENTRY ColorsProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
BOOL bRet = FALSE ;

switch (msg)
{

case WM_INITDIALOG:

InitColorStruct(hwnd, &cc) ; //initialize the CHOOSECOLOR structure
FillColorDlg(hwnd, &cc) ; //and fill the colors dialog.

nOpenColorDlgCount = 0 ;

hwndMainColor = hwnd ;

*(&ccThread1) = *(&ccThread2) = *(&cc) ;

SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEC)) ;

break ;


case UMSG_DECREMENTDLGCOUNT: //user defined message indicating
//the closure of a multithreaded dialog

/* Keep the main colors dialog buttons disabled until the last
multithreaded dialog function has returned. */

nOpenColorDlgCount-- ;

if (nOpenColorDlgCount == 0)
EnableColorButtons(hwnd, TRUE) ;

break ;


case WM_COMMAND:

switch (LOWORD(wParam))
{
case IDOK:

GetColorDlg(hwnd, &cc) ; //get user's choices

DoChooseColorStuff(hwnd, &cc) ; //do the dialog

break ;


case ID_RESETC:

SendDlgItemMessage(hwnd, ID_CUSTCOLORSC, CB_RESETCONTENT,
(WPARAM) 0, (LPARAM) 0) ;

InitColorStruct(hwnd, &cc) ;
FillColorDlg(hwnd, &cc) ;

SendDlgItemMessage(hwnd, ID_NULLSTRUCTCOLOR, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, ID_PRELOADEDCOLORS, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;

SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEC)) ;

break ;


case IDCANCEL:
EndDialog(hwnd, FALSE) ;
break ;


case ID_ADD1C:
GetDlgItemText(hwnd, ID_CUSTCOLORSC, szTemp, 100) ;

if (*szTemp)
SendDlgItemMessage(hwnd, ID_CUSTCOLORSC, CB_ADDSTRING,
(WPARAM) 0, (LPARAM) (LPTSTR) szTemp) ;
break ;

case ID_CLEAR1C:
SendDlgItemMessage(hwnd, ID_CUSTCOLORSC, CB_RESETCONTENT,
(WPARAM) 0, (LPARAM) 0) ;
break ;

case ID_MULTITHREADCOLORS:

/* Start the dialog count off at 2, disable the main dialog's
buttons, and multithread */

nOpenColorDlgCount = 2 ;

EnableColorButtons(hwnd, FALSE) ;

MultiThreadColorDlg() ;

break ;


default: break ;
}

default:


/* If the help button is pressed in the ChooseColor()
dialog, it will send a message Registered with RegisterWindowMessage()
to the parent window. The message nHelpMessage was registered
at application startup */

if (msg == nHelpMessage)
MessageBox(GetForegroundWindow(), TEXT("Hello from the help button"),
TEXT("Colors Help Button"), MB_OK | MB_APPLMODAL) ;

break ;
}

return FALSE ;
}







/************************************************************************

Function: InitColorStruct(HWND, LPCHOOSECOLOR)

Purpose: Fills the default CHOOSECOLOR structure with some default
values.

Returns: Nothing.

Comments:

************************************************************************/


void InitColorStruct(HWND hwnd, LPCHOOSECOLOR pcc)
{
int i ;

pcc->lStructSize = sizeof(CHOOSECOLOR) ;
pcc->hwndOwner = hwnd ;
pcc->hInstance = (HANDLE) hInst ;

dwColor = RGB(0, 0, 0) ;
pcc->rgbResult = dwColor ;

for (i=0; i<16; i++)
dwCustColors[i] = (RGB(255-i*10, i, i*10)) ;

pcc->lpCustColors = (LPDWORD) dwCustColors ;

pcc->Flags = CC_FULLOPEN | CC_SHOWHELP | CC_RGBINIT ;

pcc->lCustData = 0 ;

pcc->lpfnHook = ColorsHookProc ;

lstrcpy(szTemplateNameC, TEXT("clrtemp")) ; //name of custom template

pcc->lpTemplateName = (LPTSTR) szTemplateNameC ;

return ;
}








/************************************************************************

Function: FillColorDlg(HWND, LPCHOOSECOLOR)

Purpose: Fills the colors dialog with the current contents of the
CHOOSECOLOR structure passed in as the second parameter.

Returns: Nothing.

Comments:

************************************************************************/

void FillColorDlg(HWND hwnd, LPCHOOSECOLOR pcc)
{
int i ;

wsprintf(szTemp, szLongFilter, pcc->lStructSize) ;
SetDlgItemText(hwnd, ID_STRUCTSIZEC, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcc->hwndOwner) ;
SetDlgItemText(hwnd, ID_HWNDOWNERC, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcc->hInstance) ;
SetDlgItemText(hwnd, ID_HINSTANCEC, szTemp) ;

wsprintf(szTemp, szLongFilter, pcc->rgbResult) ;
SetDlgItemText(hwnd, ID_RGBRESULTC, szTemp) ;

SendDlgItemMessage(hwnd, ID_CUSTCOLORSC, CB_RESETCONTENT,
(WPARAM) 0, (LPARAM) 0) ;

for (i=0; i<16; i++)
{
wsprintf(szTemp, szLongFilter, dwCustColors[i]) ;
SendDlgItemMessage(hwnd, ID_CUSTCOLORSC, CB_ADDSTRING,
(WPARAM) 0, (LPARAM) (LPTSTR) szTemp) ;
}

SendDlgItemMessage(hwnd, ID_CUSTCOLORSC, CB_SETCURSEL,
(WPARAM) 0 , (LPARAM) 0) ;

wsprintf(szTemp, szLongFilter, pcc->Flags) ;
SetDlgItemText(hwnd, ID_FLAGSC, szTemp) ;

wsprintf(szTemp, szLongFilter, pcc->lCustData) ;
SetDlgItemText(hwnd, ID_CUSTDATAC, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) pcc->lpfnHook) ;
SetDlgItemText(hwnd, ID_HOOKC, szTemp) ;

SetDlgItemText(hwnd, ID_TEMPLATEC, (LPTSTR) pcc->lpTemplateName) ;
}







/************************************************************************

Function: GetColorDlg(HWND, LPCHOOSECOLOR)

Purpose: Retrieves the users entries in the colors dialog edit boxes
and puts them in the appropriate CHOOSECOLOR structure
members.

Returns: Nothing.

Comments:

************************************************************************/


void GetColorDlg(HWND hwnd, LPCHOOSECOLOR pcc)
{
int i ;
BOOL b ;
TCHAR szNum[30] ;

#define WSIZECC 30

GetDlgItemText(hwnd, ID_STRUCTSIZEC, szNum, WSIZECC) ;
pcc->lStructSize = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HWNDOWNERC, szNum, WSIZECC) ;
pcc->hwndOwner = (HWND) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HINSTANCEC, szNum, WSIZECC) ;
pcc->hInstance = (HANDLE) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_RGBRESULTC, szNum, WSIZECC) ;
pcc->rgbResult = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

for (i=0; i<16; i++)
{
if (SendDlgItemMessage(hwnd, ID_CUSTCOLORSC, CB_GETLBTEXT,
(WPARAM) i, (LPARAM) (LPTSTR) szNum) != CB_ERR)

dwCustColors[i] = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

else
dwCustColors[i] = (DWORD) 0 ;

*(pcc->lpCustColors + i) = dwCustColors[i] ;
}

GetDlgItemText(hwnd, ID_FLAGSC, szNum, WSIZECC) ;
pcc->Flags = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_CUSTDATAC, szNum, WSIZECC) ;
pcc->lCustData = MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HOOKC, szNum, WSIZECC) ;
pcc->lpfnHook = (LPCCHOOKPROC) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_TEMPLATEC, (LPTSTR) pcc->lpTemplateName, 50) ;

return ;
}







/************************************************************************

Function: ColorsHookProc(HWND, UINT, UINT, LONG) ;

Purpose: This function will be called before the normal ChooseColor()
logic is envoked.

Returns: FALSE to instruct ChooseColor() to proceed with it's normal
processing of the message. TRUE to discard normal processing.

Comments:

To enable the hook, type the value for "CC_ENABLEHOOK" in the
"Flags" edit box.

************************************************************************/

UINT APIENTRY ColorsHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
LPCHOOSECOLOR pCc ;
TCHAR szMsg[50] ;

switch(msg)
{
case WM_INITDIALOG:

/* During initialization of the ChooseColor() dialog, if there is a
hook proc the ChooseColor() function will send a pointer to the
current CHOOSECOLOR structure in the wParam parameter */

pCc = (LPCHOOSECOLOR) lParam ;

if (pCc->lCustData != 0L)
{
wsprintf(szMsg, TEXT("CHOOSECOLOR->lCustData is: %ld"), pCc->lCustData) ;
MessageBox(hwnd, szMsg, TEXT("lCustData Sent!"), MB_OK | MB_APPLMODAL) ;
}

SetWindowText(hwnd, TEXT("Color Hook Proc Dialog")) ;

break ;

default:
break ;
}

return FALSE ; //send msg to the common dialog code
}







/************************************************************************

Function: GetColorsResHandle(void)

Purpose: Creates a handle to the custom template and returns it to the
caller.

Returns: HANDLE to a preloaded custom template

Comments:

To use this preloaded template, mark the "Preloaded Template" checkbox
and enter CC_ENABLETEMPLATEHANDLE in the "Flags" edit box.

************************************************************************/

HANDLE GetColorsResHandle(void)
{

hResColors = FindResource(hInst, TEXT("clrtemp"), RT_DIALOG) ;

hDialogColors = LoadResource(hInst, hResColors) ;


return hDialogColors ;
}







/************************************************************************

Function:DoChooseColorStuff(HWND, LPCHOOSECOLOR)

Purpose: Does the actual calling of the ChooseColor() function.


Returns: Nothing.

Comments:

************************************************************************/

void DoChooseColorStuff(HWND hwnd, LPCHOOSECOLOR pcc)
{
BOOL bRet ;

/* If the "Preloaded template button is checked, load a handle for
the custom template and put it in the hInstance member of the
CHOOSECOLOR structure */

if (IsDlgButtonChecked(hwnd, ID_PRELOADEDCOLORS) == 1)
pcc->hInstance = GetColorsResHandle() ;


/* If the "NULL Structure" box is checked, call ChooseColor() will
a NULL pointer. Otherwise call with the current CHOOSECOLOR pointer */

if (IsDlgButtonChecked(hwnd, ID_NULLSTRUCTCOLOR) == 1)
bRet = ChooseColor((LPCHOOSECOLOR) NULL) ;
else
bRet = ChooseColor(pcc) ;

if (pcc->hInstance)
{
FreeResource(hDialogColors) ;
hDialogColors = (HANDLE) 0 ;
hResColors = (HANDLE) 0 ;
}


/* Fill the results into the main colors dialog */

FillColorDlg(hwnd, pcc) ;

wsprintf(szTemp, szShortFilter, bRet) ;
SetDlgItemText(hwnd, ID_RETURNC, szTemp) ;

wsprintf(szTemp, szLongFilter, CommDlgExtendedError()) ;
SetDlgItemText(hwnd, ID_ERRORC, szTemp) ;

}






/************************************************************************

Function:ColorThreadProc1(LPDWORD)

Purpose: Starting address for first thread


Returns: Any DWORD value.

Comments:

************************************************************************/


DWORD ColorThreadProc1(LPDWORD pdw)
{
GetColorDlg(hwndMainColor, &ccThread1) ;
DoChooseColorStuff(hwndMainColor, &ccThread1) ;

PostMessage(hwndMainColor, UMSG_DECREMENTDLGCOUNT, 0, 0L ) ;

return 0L ;
}







/************************************************************************

Function:ColorThreadProc2(LPDWORD)

Purpose: Starting address for second thread


Returns: Any DWORD value.

Comments:

************************************************************************/

DWORD ColorThreadProc2(LPDWORD pdw)
{
GetColorDlg(hwndMainColor, &ccThread2) ;
DoChooseColorStuff(hwndMainColor, &ccThread2) ;

PostMessage(hwndMainColor, UMSG_DECREMENTDLGCOUNT, 0, 0L ) ;

return 0L ;
}







/************************************************************************

Function:MultiThreadColorDlg(void)

Purpose: Creates two threads which will each create a new ChooseColor()
dialog.


Returns: Nothing.

Comments:

Do not pass any parameters to this function that may be used by the
ChooseColor dialog routines because this function will return before
the new threads are finished.

************************************************************************/


void MultiThreadColorDlg(void)
{

dwColorThreadParm1 = dwColorThreadParm2 = 0L ;

if (!(hColorThread1 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
(LPTHREAD_START_ROUTINE) ColorThreadProc1,
&dwColorThreadParm1, CREATE_SUSPENDED, &dwColorThreadID1)))

{
MessageBox(GetForegroundWindow(), TEXT("Error creating thread 1"), NULL,
MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL) ;

nOpenColorDlgCount = 0 ;

EnableColorButtons(hwndMainColor, TRUE) ;

return ;
}


if (!(hColorThread2 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
(LPTHREAD_START_ROUTINE) ColorThreadProc2,
&dwColorThreadParm2, CREATE_SUSPENDED, &dwColorThreadID2)))
{
MessageBox(GetForegroundWindow(), TEXT("Error creating thread 2"), NULL,
MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL) ;

nOpenColorDlgCount = 0 ;

EnableColorButtons(hwndMainColor, TRUE) ;

return ;
}

ResumeThread(hColorThread1) ;

ResumeThread(hColorThread2) ;

return ;
}





/************************************************************************

Function:EnableColorButtons(HWND, BOOL)

Purpose: Enables or disables the buttons on the main colors dialog.
Necessary when multithreading.

Returns: Nothing.

Comments:

************************************************************************/


void EnableColorButtons(HWND hwnd, BOOL bEnable)
{
EnableWindow(GetDlgItem(hwnd, IDOK), bEnable) ;
EnableWindow(GetDlgItem(hwnd, IDCANCEL), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_RESETC), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_MULTITHREADCOLORS), bEnable) ;
}