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) ; 
}