PRINT.C

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

File: print.c

Purpose: To manage CDTEST's print dialog box.


Functions:

DoPrintDlg() -- Creates CDTEST's print dialog box.

PrintProc() -- Callback function for CDTEST's print dialog box.

DevnamesProc() -- Callback function for CDTESTS Devnames dlg box.

DevmodeProc() -- Callback function for CDTESTS Devmode dlg box.

InitPrintStruct() -- Fills a PRINTDLG struct with some default values.

FillPrintDlg() -- Fills CDTEST's print dialog with contents of a
PRINTDLG structure.

GetPrintDlg() -- Retrieves the users edits from CDTEST's print dlg.

FillDevnamesDlg() -- Fills CDTEST's Devnames dialog with the contents
of a DEVNAMES structure.

GetDevnamesDlg() -- Retrieves the user's edits from CDTEST's devnames dlg.

FillDevmodeDlg() -- Fills CDTEST's devmode dialog with the contents of
a DEVMODE structure.

GetDevmodeDlg() -- Retrieves the user's edits from CDTEST's devmode dlg.

GetPrintDlgHandle() -- Loads and returns a handle to a Print dlg custom template.

GetSetupDlgHandle() -- Loads and returns a handle to a Setup dlg custom template.

PrintHookProc() -- Callback function for PRINTDLG->lpfnPrintHook and
for PRINTDLG->lpfnSetupHook

PrintMultiProc1() -- Starting address for multithread option thread 1

PrintMultiProc2() -- Starting address for multithread option thread 2

MultiThreadPrintDlg() -- Creates two threads which each call PrintDlg()

EnablePrintControls() -- Enables or disables CDTEST's print dlg controls.

DoPrintDlgStuff() -- Calls PrintDlg()

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


#include <windows.h>
#include <commdlg.h>
#include <stdlib.h>
#include <winnls.h>
#include "cdtest.h"
#include "print.h"
#include "devnames.h"
#include "devmode.h"
#include "dlgs.h"



/* Externs, prototypes, variable declarations for print.c */

extern UINT uMode ;
extern LONG MyAtol(LPTSTR, BOOL, LPBOOL) ;
UINT APIENTRY PrintHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam) ;
void InitPrintStruct(HWND, LPPRINTDLG) ;
void FillPrintDlg(HWND, LPPRINTDLG) ;
void GetPrintDlg(HWND, LPPRINTDLG) ;
void FillDevnamesDlg(HWND, LPPRINTDLG) ;
void GetDevnamesDlg(HWND, LPPRINTDLG) ;
void FillDevmodeDlg(HWND, LPPRINTDLG) ;
void GetDevmodeDlg(HWND, LPPRINTDLG) ;
HANDLE GetPrintDlgHandle(void) ;
HANDLE GetSetupDlgHandle(void) ;
void DoPrintDlgStuff(HWND, LPPRINTDLG) ;

HANDLE hResPrint ;
HANDLE hDialogPrint ;
PRINTDLG pd ;
HANDLE hDevNames ;
HANDLE hDevMode ;

TCHAR szDriverOffset[100] ;
TCHAR szDeviceOffset[100] ;
TCHAR szOutputOffset[100] ;
TCHAR szPrintTempName[40] ;
TCHAR szSetupTempName[40] ;


/* Multithreading function declarations, variables */

DWORD PrintMultiProc1(LPDWORD) ;
DWORD PrintMultiProc2(LPDWORD) ;
void MultiThreadPrintDlg(void) ;
void EnablePrintControls(HWND, BOOL) ;

HANDLE hPrintThread1 ;
HANDLE hPrintThread2 ;
DWORD dwPrintThreadID1 ;
DWORD dwPrintThreadID2 ;
DWORD dwPrintThreadParm1 ;
DWORD dwPrintThreadParm2 ;
PRINTDLG pdThread1 ;
PRINTDLG pdThread2 ;
HWND hwndMainPrint ;
int nOpenDialogCount ;

HBRUSH hBrushDlg ;
HBRUSH hBrushEdit ; //brush handles for new colors done with hook proc
HBRUSH hBrushButton ;





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

Function: DoPrintDialog(HWND)

Purpose: Creates CDTEST's print dialog box.

Returns: Nothing.

Comments: There is only one dialog for both Print Setup and Print Print.
The Print Print dialog is the default. To create the Print
Setup dialog, enter the value for PD_PRINTSETUP into the
"Flags" edit box and click OK.

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

void DoPrintDialog(HWND hwnd)
{


DialogBox(hInst, MAKEINTRESOURCE(ID_PRINTDIALOG),
hwnd, PrintProc) ;

}







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

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

Purpose: Callback function for CDTEST's print dialog box.

Returns: TRUE or FALSE depending on the situation/message.

Comments:

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

BOOL APIENTRY PrintProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
switch (msg)
{
case WM_INITDIALOG:

InitPrintStruct(hwnd, &pd) ;
FillPrintDlg(hwnd, &pd) ;

*(&pdThread1) = *(&pdThread2) = *(&pd) ;

hwndMainPrint = hwnd ;

nOpenDialogCount = 0 ;

SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEP)) ;

break ;


case UMSG_DECREMENTDLGCOUNT: //user defined message that is send when
//each thread created when multithreading ends
nOpenDialogCount-- ;

if (nOpenDialogCount == 0) //once both multitheading dlgs
EnablePrintControls(hwnd, TRUE) ; //are done, enable the controls again

break ;


case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
GetPrintDlg(hwnd, &pd) ;
DoPrintDlgStuff(hwnd, &pd) ;
break ;

case IDCANCEL:

if (pd.hDC)
ReleaseDC(hwnd, pd.hDC) ;

EndDialog(hwnd, FALSE) ;
break ;

case ID_RESETPRINT:
SetFocus(GetDlgItem(hwnd, ID_STRUCTSIZEP)) ;
InitPrintStruct(hwnd, &pd) ;
FillPrintDlg(hwnd, &pd) ;
SendDlgItemMessage(hwnd, ID_PRESETUPP, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, ID_PREPRINTP, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
SendDlgItemMessage(hwnd, ID_NULLSTRUCTP, BM_SETCHECK, (WPARAM)0, (LPARAM)0) ;
break ;

case ID_EDITDEVNAMES:
DialogBox(hInst, MAKEINTRESOURCE(ID_DEVNAMESDIALOG),
hwnd, DevnamesProc) ;
break ;

case ID_EDITDEVMODE:
DialogBox(hInst, MAKEINTRESOURCE(ID_DEVMODEDIALOG),
hwnd, DevmodeProc) ;
break ;

case ID_MULTITHREADPRINT:
nOpenDialogCount = 2 ;
EnablePrintControls(hwnd, FALSE) ;
MultiThreadPrintDlg() ;
break ;

default: break ;
}
}

default:

/* If the help button is pressed in the PrintDlg() dialog box,
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("Print Help Button"), MB_OK | MB_APPLMODAL) ;
break ;
}

return FALSE ;
}








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

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

Purpose: Callback function for the Devnames dialog box

Returns: TRUE or FALSE depending on situation / message

Comments:

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

BOOL APIENTRY DevnamesProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
switch (msg)
{
case WM_INITDIALOG:
FillDevnamesDlg(hwnd, &pd) ;
break ;

case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
GetDevnamesDlg(hwnd, &pd) ;
EndDialog(hwnd, TRUE) ;
break ;

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

default: break ;
}
}

default: break ;
}

return FALSE ;
}






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

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

Purpose: Callback function for the Devmode dialog box

Returns: TRUE or FALSE depending on situation / message

Comments:

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

BOOL APIENTRY DevmodeProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
switch (msg)
{
case WM_INITDIALOG:
FillDevmodeDlg(hwnd, &pd) ;
break ;

case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
GetDevmodeDlg(hwnd, &pd) ;
EndDialog(hwnd, TRUE) ;
break ;

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

default: break ;
}
}

default: break ;
}

return FALSE ;
}








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

Function: InitPrintStruct(HWND, LPPRINTDLG)

Purpose: Fills a PRINTDLG structure with some default values.

Returns: Nothing.

Comments:

In order to fill in the hDevMode and hDevNames PRINTDLG structure
elements, a call to PrintDlg() must be made with the
(PD_RETURNDEFAULT | PD_RETURNDC) flag bits set.

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

void InitPrintStruct(HWND hwnd, LPPRINTDLG ppd)
{
DWORD dwTempFlags = 0 ;

ppd->lStructSize = sizeof(PRINTDLG) ;
ppd->hwndOwner = hwnd ;
ppd->hDevMode = (HANDLE) 0 ;
ppd->hDevNames = (HANDLE) 0 ;
ppd->hDC = (HDC) 0 ;
ppd->Flags = PD_RETURNDC | PD_COLLATE | PD_SHOWHELP | PD_PAGENUMS ;
ppd->nFromPage = 1 ;
ppd->nToPage = 10 ;
ppd->nMinPage = 0 ;
ppd->nMaxPage = 9 ;
ppd->nCopies = 1000 ;
ppd->hInstance = (HANDLE) hInst ;
ppd->lCustData = 0L ;

ppd->lpfnPrintHook = PrintHookProc ;
ppd->lpfnSetupHook = PrintHookProc ;

lstrcpy(szPrintTempName, TEXT("prtemp1")) ;
ppd->lpPrintTemplateName = szPrintTempName ;

lstrcpy(szSetupTempName, TEXT("prtemp2")) ;
ppd->lpSetupTemplateName = szSetupTempName ;

ppd->hPrintTemplate = (HANDLE) 0 ; //these are unknown right now
ppd->hSetupTemplate = (HANDLE) 0 ;


/* Let's fill the hDevMode and hDevNames structures. */
/* This call should just return handles to structures of this */
/* type filled with the info for the default printer */

dwTempFlags = ppd->Flags ;
ppd->Flags = PD_RETURNDEFAULT | PD_RETURNDC ;
PrintDlg(ppd) ;

ppd->Flags = dwTempFlags ;
}







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

Function: FillPrintDlg(HWND, LPPRINTDLG)

Purpose: Fills CDTEST's print dialog with the contents of a
PRINTDLG structure.

Returns: Nothing.

Comments:

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


void FillPrintDlg(HWND hwnd, LPPRINTDLG ppd)
{
wsprintf(szTemp, szLongFilter, ppd->lStructSize) ;
SetDlgItemText(hwnd, ID_STRUCTSIZEP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hwndOwner) ;
SetDlgItemText(hwnd, ID_HWNDOWNERP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hDevMode) ;
SetDlgItemText(hwnd, ID_HDEVMODEP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hDevNames) ;
SetDlgItemText(hwnd, ID_HDEVNAMESP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hDC) ;
SetDlgItemText(hwnd, ID_HDCP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->Flags) ;
SetDlgItemText(hwnd, ID_FLAGSP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->nFromPage) ;
SetDlgItemText(hwnd, ID_FROMPAGEP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->nToPage) ;
SetDlgItemText(hwnd, ID_TOPAGEP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->nMinPage) ;
SetDlgItemText(hwnd, ID_MINPAGEP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->nMaxPage) ;
SetDlgItemText(hwnd, ID_MAXPAGEP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->nCopies) ;
SetDlgItemText(hwnd, ID_COPIESP, szTemp) ;

wsprintf(szTemp, szLongFilter, ppd->hInstance) ;
SetDlgItemText(hwnd, ID_HINSTANCEP, szTemp) ;

wsprintf(szTemp, szLongFilter, ppd->lCustData) ;
SetDlgItemText(hwnd, ID_CUSTDATAP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->lpfnPrintHook) ;
SetDlgItemText(hwnd, ID_PRINTHOOKP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->lpfnSetupHook) ;
SetDlgItemText(hwnd, ID_SETUPHOOKP, szTemp) ;

SetDlgItemText(hwnd, ID_LPPRINTTEMPP, ppd->lpPrintTemplateName) ;

SetDlgItemText(hwnd, ID_LPSETUPTEMPP, ppd->lpSetupTemplateName) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hPrintTemplate) ;
SetDlgItemText(hwnd, ID_HPRINTTEMPP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hSetupTemplate) ;
SetDlgItemText(hwnd, ID_HSETUPTEMPP, szTemp) ;
}









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

Function: GetPrintDlg(HWND, LPPRINTDLG)

Purpose: Fills a PRINTDLG structure with the users choices in CDTEST's
print dialog box.

Returns: Nothing.

Comments:

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

void GetPrintDlg(HWND hwnd, LPPRINTDLG ppd)
{
BOOL b ;
TCHAR szNum[20] ;

#define WMAX 20

GetDlgItemText(hwnd, ID_STRUCTSIZEP, szNum, WMAX) ;
ppd->lStructSize = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HWNDOWNERP, szNum, WMAX) ;
ppd->hwndOwner = (HWND) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HDEVMODEP, szNum, WMAX) ;
ppd->hDevMode = (HANDLE) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HDEVNAMESP, szNum, WMAX) ;
ppd->hDevNames = (HANDLE) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HDCP, szNum, WMAX) ;
ppd->hDC = (HDC) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_FLAGSP, szNum, WMAX) ;
ppd->Flags = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_FROMPAGEP, szNum, WMAX) ;
ppd->nFromPage = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_TOPAGEP, szNum, WMAX) ;
ppd->nToPage = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_MINPAGEP, szNum, WMAX) ;
ppd->nMinPage = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_MAXPAGEP, szNum, WMAX) ;
ppd->nMaxPage = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_COPIESP, szNum, WMAX) ;
ppd->nCopies = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HINSTANCEP, szNum, WMAX) ;
ppd->hInstance = (HANDLE) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_CUSTDATAP, szNum, WMAX) ;
ppd->lCustData = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_PRINTHOOKP, szNum, WMAX) ;
ppd->lpfnPrintHook = (LPPRINTHOOKPROC) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_SETUPHOOKP, szNum, WMAX) ;
ppd->lpfnSetupHook = (LPSETUPHOOKPROC) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_LPPRINTTEMPP, szPrintTempName, 100) ;

GetDlgItemText(hwnd, ID_LPSETUPTEMPP, szSetupTempName, 100) ;

GetDlgItemText(hwnd, ID_HPRINTTEMPP, szNum, WMAX) ;
ppd->hPrintTemplate = (HANDLE) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_HSETUPTEMPP, szNum, WMAX) ;
ppd->hSetupTemplate = (HANDLE) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

}








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

Function: FillDevnamesDlg(HWND, LPPRINTDLG)

Purpose: Fills CDTEST's devnames dialog box with the values in
The hDevNames structure member of a PRINTDLG structure.

Returns: Nothing.

Comments:

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


void FillDevnamesDlg(HWND hwnd, LPPRINTDLG ppd)
{
LPDEVNAMES pn = (LPDEVNAMES) 0 ;

if (ppd->hDevNames == (HANDLE) 0)
return ;

pn = (LPDEVNAMES) GlobalLock(ppd->hDevNames) ;
if (pn == (LPDEVNAMES) NULL) return ;


/* To find the strings in this block of memory, add the correct
offset to the original pointer returned by GlobalLock() */

SetDlgItemText(hwnd, ID_WDRIVEROFF, (LPTSTR) pn + pn->wDriverOffset) ;

SetDlgItemText(hwnd, ID_WDEVICEOFF, (LPTSTR) pn + pn->wDeviceOffset) ;

SetDlgItemText(hwnd, ID_WOUTPUTOFF, (LPTSTR) pn + pn->wOutputOffset) ;


wsprintf(szTemp, szShortFilter, (int) pn->wDefault) ;
SetDlgItemText(hwnd, ID_WDEFAULT, szTemp) ;


GlobalUnlock(ppd->hDevNames) ;
}







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

Function: GetDevnamesDlg(HWND, LPPRINTDLG)

Purpose: Retrieves the user's choices in CDTEST's devnames dialog box,
Allocates some memory to hold a new DEVNAMES structure, fills
the users choices into the new DEVNAMES structure, and sets
the hDevNames member of a PRINTDLG structure to this new
memory handle.


Returns: Nothing.

Comments:

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

void GetDevnamesDlg(HWND hwnd, LPPRINTDLG ppd)
{
BOOL b ;
TCHAR szNum[30] ;
LPDEVNAMES pn ;
TCHAR sz1[100] ;
TCHAR sz2[100] ;
TCHAR sz3[100] ;
DWORD dwSize ;
int n1, n2, n3 ;

GetDlgItemText(hwnd, ID_WDRIVEROFF, sz1, 100) ;
GetDlgItemText(hwnd, ID_WDEVICEOFF, sz2, 100) ;
GetDlgItemText(hwnd, ID_WOUTPUTOFF, sz3, 100) ;

n1 = lstrlen(sz1) ;
n2 = lstrlen(sz2) ;
n3 = lstrlen(sz3) ;

if (hDevNames)
{
GlobalFree(hDevNames) ;
hDevNames = (HANDLE) 0 ;
}


/* allocate size of everything + 5 extra bytes for zeroes */

dwSize = sizeof(DEVNAMES) + ((n1+n2+n3+5) * sizeof(TCHAR)) ;


/* Allocate the memory and lock it down */

if (!(hDevNames = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize)))
{
MessageBox(hwnd, TEXT("Can't Alloc memory for hDevNames!"),
TEXT("Fatal Error!"), MB_OK | MB_APPLMODAL) ;
return ;
}

if (!(pn = (LPDEVNAMES) GlobalLock(hDevNames)))
{
MessageBox(hwnd, TEXT("Can't Lock New hDevNames memory!"),
TEXT("Fatal Error"), MB_OK | MB_APPLMODAL) ;

GlobalFree(hDevNames) ;

hDevNames = (HANDLE) 0 ;

return ;
}


/* skip over devnames and copy string 1 there. Make sure to
divide by sizeof(TCHAR) or the compiler will create a pointer
that points too far if you compile as a UNICODE program */

pn->wDriverOffset = sizeof(DEVNAMES) / sizeof(TCHAR) ;
lstrcpy((LPTSTR) pn + pn->wDriverOffset, (LPTSTR) sz1) ;



/* skip over string 1 and add string 1 with a zero between them */

pn->wDeviceOffset = pn->wDriverOffset + n1 + 1 ;
lstrcpy((LPTSTR) pn + pn->wDeviceOffset, (LPTSTR) sz2) ;



/* skip over string 2 and put string 3 there with a zero between them */

pn->wOutputOffset = pn->wDeviceOffset + n2 + 1 ;
lstrcpy((LPTSTR) pn + pn->wOutputOffset, (LPTSTR) sz3) ;


GetDlgItemText(hwnd, ID_WDEFAULT, szNum, 30) ;
pn->wDefault = (WORD) MyAtol(szNum, uMode == IDM_HEXMODE, &b) ;

GlobalUnlock(hDevNames) ;

ppd->hDevNames = hDevNames ;

wsprintf(szTemp, szLongFilter, ppd->hDevNames) ;
SetDlgItemText(GetParent(hwnd), ID_HDEVNAMESP, szTemp) ;

}






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

Function: FillDevmodeDlg(HWND, LPPRINTDLG)

Purpose: Fills CDTEST's devmode dialog with the contents of the DEVMODE
structure handle of a PRINTDLG structure.


Returns: Nothing.

Comments:

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

void FillDevmodeDlg(HWND hwnd, LPPRINTDLG ppd)
{
LPDEVMODE p ;

if (ppd->hDevMode == (HANDLE) 0)
return ;

p = (LPDEVMODE) GlobalLock(ppd->hDevMode) ;
if (p == (LPDEVMODE) NULL) return ;

SetDlgItemText(hwnd, ID_DMDEVNAME, (LPTSTR) p->dmDeviceName) ;

wsprintf(szTemp, szShortFilter, (int) p->dmSpecVersion) ;
SetDlgItemText(hwnd, ID_DMSPECVER, szTemp) ;

wsprintf(szTemp, szShortFilter, (int) p->dmDriverVersion) ;
SetDlgItemText(hwnd, ID_DMDRIVERVER, szTemp) ;

wsprintf(szTemp, szShortFilter, (int) p->dmSize) ;
SetDlgItemText(hwnd, ID_DMSIZEDEV, szTemp) ;

wsprintf(szTemp, szShortFilter, (int) p->dmDriverExtra) ;
SetDlgItemText(hwnd, ID_DMDRIVEREXTRA, szTemp) ;

wsprintf(szTemp, szShortFilter, (int) p->dmFields) ;
SetDlgItemText(hwnd, ID_DMFIELDS, szTemp) ;

wsprintf(szTemp, szShortFilter, (int) p->dmOrientation) ;
SetDlgItemText(hwnd, ID_DMORIENTATION, szTemp) ;

wsprintf(szTemp, szShortFilter, (int) p->dmPaperSize) ;
SetDlgItemText(hwnd, ID_DMPAPERSIZE, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmPaperLength) ;
SetDlgItemText(hwnd, ID_DMPAPERLENGTH, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmPaperWidth) ;
SetDlgItemText(hwnd, ID_DMPAPERWIDTH, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmScale) ;
SetDlgItemText(hwnd, ID_DMSCALE, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmCopies) ;
SetDlgItemText(hwnd, ID_DMCOPIES, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmDefaultSource) ;
SetDlgItemText(hwnd, ID_DMDEFAULTSOURCE, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmPrintQuality) ;
SetDlgItemText(hwnd, ID_DMPRINTQUALITY, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmColor) ;
SetDlgItemText(hwnd, ID_DMCOLOR, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmDuplex) ;
SetDlgItemText(hwnd, ID_DMDUPLEX, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmCollate) ;
SetDlgItemText(hwnd, ID_DMCOLLATE, szTemp) ;

SetDlgItemText(hwnd, ID_DMFORMNAME, (LPTSTR) p->dmFormName) ;

wsprintf(szTemp, szLongFilter, p->dmBitsPerPel) ;
SetDlgItemText(hwnd, ID_DMBITSPERPEL, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmPelsWidth) ;
SetDlgItemText(hwnd, ID_DMPELSWIDTH, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmPelsHeight) ;
SetDlgItemText(hwnd, ID_DMPELSHEIGHT, szTemp) ;

wsprintf(szTemp, szLongFilter, p->dmDisplayFrequency) ;
SetDlgItemText(hwnd, ID_DMDISPLAYFREQ, szTemp) ;

GlobalUnlock(ppd->hDevMode) ;
}









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

Function: GetDevmodeDlg(HWND, LPPRINTDLG)

Purpose: Retrieves the user's edits in CDTEST's DEVMODE dialog box,
allocates memory for a new DEVMODE structure, fills that
memory with the user's edits, and puts a handle to that
memory in the hDevMode member of a PRINTDLG structure.

Returns: Nothing.

Comments:

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

void GetDevmodeDlg(HWND hwnd, LPPRINTDLG ppd)
{
LPDEVMODE p ;
BOOL b ;
TCHAR szNum[30] ;

#define WMAXDEV 30

if (hDevMode)
{
GlobalFree(hDevMode) ;
hDevMode = (HANDLE) 0 ;
}

if (!(hDevMode = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, sizeof(DEVMODE))))
{
MessageBox(hwnd, TEXT("Can't allocate memory for hDevMode"),
TEXT("Fatal Error"), MB_OK | MB_APPLMODAL) ;
return ;
}

if (!(p = (LPDEVMODE) GlobalLock(hDevMode)))
{
MessageBox(hwnd, TEXT("Can't lock memory for hDevMode"),
TEXT("Fatal Error"), MB_OK | MB_APPLMODAL) ;

GlobalFree(hDevMode) ;
hDevMode = (HANDLE) 0 ;

return ;
}

GetDlgItemText(hwnd, ID_DMDEVNAME, p->dmDeviceName, 32) ;

GetDlgItemText(hwnd, ID_DMSPECVER, szNum, WMAXDEV) ;
p->dmSpecVersion = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMDRIVERVER, szNum, WMAXDEV) ;
p->dmDriverVersion = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMSIZEDEV, szNum, WMAXDEV) ;
p->dmSize = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMDRIVEREXTRA, szNum, WMAXDEV) ;
p->dmDriverExtra = (WORD) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMFIELDS, szNum, WMAXDEV) ;
p->dmFields = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMORIENTATION, szNum, WMAXDEV) ;
p->dmOrientation = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMPAPERSIZE, szNum, WMAXDEV) ;
p->dmPaperSize = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMPAPERLENGTH, szNum, WMAXDEV) ;
p->dmPaperLength = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMPAPERWIDTH, szNum, WMAXDEV) ;
p->dmPaperWidth = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMSCALE, szNum, WMAXDEV) ;
p->dmScale = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMCOPIES, szNum, WMAXDEV) ;
p->dmCopies = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMDEFAULTSOURCE, szNum, WMAXDEV) ;
p->dmDefaultSource = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMPRINTQUALITY, szNum, WMAXDEV) ;
p->dmPrintQuality = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMCOLOR, szNum, WMAXDEV) ;
p->dmColor = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMDUPLEX, szNum, WMAXDEV) ;
p->dmDuplex = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMCOLLATE, szNum, WMAXDEV) ;
p->dmCollate = (short) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMFORMNAME, p->dmFormName, 32) ;

GetDlgItemText(hwnd, ID_DMBITSPERPEL, szNum, WMAXDEV) ;
p->dmBitsPerPel = (USHORT) MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMPELSWIDTH, szNum, WMAXDEV) ;
p->dmPelsWidth = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMPELSHEIGHT, szNum, WMAXDEV) ;
p->dmPelsHeight = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GetDlgItemText(hwnd, ID_DMDISPLAYFREQ, szNum, WMAXDEV) ;
p->dmDisplayFrequency = MyAtol(szNum, uMode==IDM_HEXMODE, &b) ;

GlobalUnlock(hDevMode) ;
ppd->hDevMode = hDevMode ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hDevMode) ;
SetDlgItemText(GetParent(hwnd), ID_HDEVMODEP, szTemp) ;
}






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

Function: GetPrintDlgHandle(void)

Purpose: Finds the custom Print dialog template in the EXE, loads it
into a handle, and returns the handle.

Returns: Nothing.

Comments:

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

HANDLE GetPrintDlgHandle(void)
{
hResPrint = FindResource(hInst, TEXT("prtemp1"), RT_DIALOG) ;

hDialogPrint = LoadResource(hInst, hResPrint) ;


return hDialogPrint ;
}








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

Function: GetSetupDlgHandle(void)

Purpose: Finds the custom Setup dialog template in the EXE, loads it
into a handle, and returns the handle.

Returns: Nothing.

Comments:

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

HANDLE GetSetupDlgHandle(void)
{
hResPrint = FindResource(hInst, TEXT("prtemp2"), RT_DIALOG) ;

hDialogPrint = LoadResource(hInst, hResPrint) ;

return hDialogPrint ;
}








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

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

Purpose: A callback function that will receive messages intended for
the PrintDlg() dialog boxes before the normal common dialog
routine receives them.


Returns: FALSE to allow the common dialogs to process the message
with its normal logic. TRUE to discard the message.

Comments:

To enable this function for the Print dialog in CDTEST, enter the
value for PD_ENABLEPRINTHOOK in the "Flags" edit box.

To enable this function for the Setup dialog in CDTEST, enter the
value for (PD_ENABLESETUPHOOK | PD_PRINTSETUP) in the "Flags" edit box.

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


UINT APIENTRY PrintHookProc(HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
LPPRINTDLG pPr ;
TCHAR szMsg[50] ;

switch(msg)
{
case WM_INITDIALOG:

pPr = (LPPRINTDLG) lParam ;

if (pPr->lCustData != 0)
{
wsprintf(szMsg, TEXT("PRINTDLG->lCustData is: %ld"), pPr->lCustData) ;

MessageBox(hwnd, szMsg, TEXT("lCustData Sent!"), MB_OK | MB_APPLMODAL) ;
}

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

break ;

/* use the WM_CTLCOLOR* messages to change the color of the Open
dialog */

case WM_CTLCOLORDLG:

if (!hBrushDlg)
hBrushDlg = GetStockObject(LTGRAY_BRUSH) ;

return (UINT) hBrushDlg ;

break ;


case WM_CTLCOLORBTN:

SetBkMode((HDC) wParam, TRANSPARENT) ; //sets background color
//for push and check box
//buttons...

if (!hBrushButton)
hBrushButton = GetStockObject(LTGRAY_BRUSH) ;

return (UINT) hBrushButton ;

break ;


case WM_CTLCOLORSTATIC:

SetTextColor((HDC) wParam, RGB(0x00, 0xff, 0x00)) ; //green
SetBkMode((HDC) wParam, TRANSPARENT) ; //transparent text

if (!hBrushDlg)
hBrushDlg = GetStockObject(LTGRAY_BRUSH) ;

return (UINT) hBrushDlg ;

break ;


default:
break ;
}

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








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

Function: PrintMultiProc1(LPDWORD)

Purpose: Is the starting address for the first new thread when
multithreading.

Returns: Any DWORD value.

Comments:
The new thread will start executing here and will end when
the PrintDlg() function returns and it has posted a message
to the CDTEST's print dialog window saying that one of the
two multithreading dialogs been terminated.

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

DWORD PrintMultiProc1(LPDWORD pdw)
{
GetPrintDlg(hwndMainPrint, &pdThread1) ;

DoPrintDlgStuff(hwndMainPrint, &pdThread1) ;

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

return 0L ;
}









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

Function: PrintMultiProc2(LPDWORD)

Purpose: Is the starting address for the second new thread when
multithreading.

Returns: Any DWORD value.

Comments:
The new thread will start executing here and will end when
the PrintDlg() function returns and it has posted a message
to the CDTEST's print dialog window saying that one of the
two multithreading dialogs been terminated.

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

DWORD PrintMultiProc2(LPDWORD pdw)
{
GetPrintDlg(hwndMainPrint, &pdThread2) ;

DoPrintDlgStuff(hwndMainPrint, &pdThread2) ;

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

return 0L ;
}








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

Function: MultiThreadPrintDlg(void)

Purpose: Is the starting address for the first new thread when
multithreading.

Returns: Any DWORD value.

Comments:
The new thread will start executing here and will end when
the PrintDlg() function returns and it has posted a message
to the CDTEST's print dialog window saying that one of the
two multithreading dialogs been terminated.

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

void MultiThreadPrintDlg(void)
{

dwPrintThreadParm1 = dwPrintThreadParm2 = 0L ;

if (!(hPrintThread1 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
(LPTHREAD_START_ROUTINE) PrintMultiProc1,
&dwPrintThreadParm1, CREATE_SUSPENDED, &dwPrintThreadID1)))

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

nOpenDialogCount = 0 ;

EnablePrintControls(hwndMainPrint, TRUE) ;

return ;
}


if (!(hPrintThread2 = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0,
(LPTHREAD_START_ROUTINE) PrintMultiProc2,
&dwPrintThreadParm2, CREATE_SUSPENDED, &dwPrintThreadID2)))
{
MessageBox(GetForegroundWindow(), TEXT("Error creating thread 2"), NULL,
MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL) ;

nOpenDialogCount = 0 ;

EnablePrintControls(hwndMainPrint, TRUE) ;

return ;
}

ResumeThread(hPrintThread1) ;

ResumeThread(hPrintThread2) ;

return ;
}







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

Function: EnablePrintControls(HWND, BOOL)

Purpose: Enable or disable CDTEST's print dialog's controls.

Returns: Nothing.

Comments: This is necessary when CDTEST is multithreading.

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

void EnablePrintControls(HWND hwnd, BOOL bEnable)
{
EnableWindow(GetDlgItem(hwnd, IDOK), bEnable) ;
EnableWindow(GetDlgItem(hwnd, IDCANCEL), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_RESETPRINT), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_MULTITHREADPRINT), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_EDITDEVMODE), bEnable) ;
EnableWindow(GetDlgItem(hwnd, ID_EDITDEVNAMES), bEnable) ;
}






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

Function: DoPrintDlgStuff(HWND, LPPRINTDLG)

Purpose: Calls PrintDlg() with the correct parameters.

Returns: Nothing.

Comments:

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


void DoPrintDlgStuff(HWND hwnd, LPPRINTDLG ppd)
{
BOOL bRet = FALSE ;


/* Figure out how the user want's to call PrintDlg() */

if (IsDlgButtonChecked(hwnd, ID_PREPRINTP) == 1)
ppd->hPrintTemplate = GetPrintDlgHandle() ;

if (IsDlgButtonChecked(hwnd, ID_PRESETUPP) == 1)
ppd->hSetupTemplate = GetSetupDlgHandle() ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hPrintTemplate) ;
SetDlgItemText(hwnd, ID_HPRINTTEMPP, szTemp) ;

wsprintf(szTemp, szLongFilter, (DWORD) ppd->hSetupTemplate) ;
SetDlgItemText(hwnd, ID_HSETUPTEMPP, szTemp) ;



/* Call the function */

if (IsDlgButtonChecked(hwnd, ID_NULLSTRUCTP) == 1)
bRet = PrintDlg((LPPRINTDLG) NULL) ;
else
bRet = PrintDlg(ppd) ;



/* Clean up and show results */

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

SetDlgItemInt(hwnd, ID_RETURNP, bRet, TRUE) ;

if (hDialogPrint)
{
FreeResource(hDialogPrint) ; //obsolete call, but
hDialogPrint = (HANDLE) 0 ; //it's possible that this
hResPrint = (HANDLE) 0 ; //might be recompiled for win 3.x
}

pd.hDevMode = ppd->hDevMode ; //need to fix this so that FillDevnamesDlg()
pd.hDevNames = ppd->hDevNames ; //and FillDevmodeDlg() work...

FillPrintDlg(hwnd, ppd) ;

if (ppd->hDC) //release the HDC after its value is
//returned to the test app
{
ReleaseDC(ppd->hwndOwner, ppd->hDC) ;
ppd->hDC = (HDC) 0 ;
}
}