backprnt.c
/*
* BackPrnt.c * * Sample code for "Multithreading Applications in Win32" * This is from Chapter 2, Listing 2-6 * * Demonstrates background printing
*/
#define
WIN32_LEAN_AND_MEAN
#include
<
stdio.h
>
#include
<
stdlib.h
>
#include
<
windows.h
>
#include
<
windowsx.h
>
#include
<
commdlg.h
>
#include
"
resource.h
"
#include
"
MtVerify.h
"
//
//
Macro definitions
//
#define
WM_SHOWBITMAP WM_APP
#define
MAX_PRINT_JOBS 64
//
//
Structures
//
typedef
struct
{
//
Information passed to background thread for printing
HWND hDlg; HWND hWndParent; HDC hDc; BOOL bPrint;
//
TRUE if printing;
char
szText[
256
];} ThreadPrintInfo;
//
//
Global variables
//
HANDLE hInst;HBITMAP gbmpDisplay;RECT gDisplayRect;
int
gNumPrinting
=
0
;
//
Handle to each created thread
HANDLE gPrintJobs[
64
];
//
Height of bitmap returned by DrawText
int
iHeight;
//
HWND of the dialog so other threads can find it.
HWND hDlgMain;
//
//
Function declarations
//
int
APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int
nCmdShow);LRESULT CALLBACK MainWndProc(HWND hWnd, unsigned msg, WPARAM wParam, LPARAM lParam);LRESULT CALLBACK PrintDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);BOOL PrintDlg_OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam);
void
PrintDlg_OnCommand(HWND hDlg,
int
id, HWND hwndCtl, UINT codeNotify);
void
PrintDlg_OnPaint(HWND hwnd);
void
PrintText(HWND hwndParent,
char
*
pszText);
void
PrintToDisplay(HWND hwndParent,
char
*
pszText);LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);DWORD WINAPI BackgroundPrintThread(LPVOID pVoid);
/
//
//
//
WinMain
//
//
Main entry point of application. This will be a
//
dialog based app, not a normal window, so this
//
routine acts a little differently than "normal".
//
int
APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int
nCmdShow){ MSG msg; HWND hWnd; WNDCLASS wc;
int
index; hInst
=
hInstance;
if
(
!
hPrevInstance) { memset(
&
wc,
0
,
sizeof
(wc)); wc.lpfnWndProc
=
MainWndProc; wc.hInstance
=
hInstance; wc.hIcon
=
LoadIcon (hInstance,
"
GenIco
"
); wc.hCursor
=
LoadCursor(NULL,IDC_ARROW); wc.hbrBackground
=
GetSysColorBrush(COLOR_BACKGROUND); wc.lpszMenuName
=
"
PRINTING_MENU
"
; wc.lpszClassName
=
"
PrintDlgClass
"
;
if
(
!
RegisterClass(
&
wc))
return
FALSE; } hWnd
=
CreateWindow(
"
PrintDlgClass
"
,
"
Background Printing
"
, WS_OVERLAPPED
|
WS_CAPTION
|
WS_MINIMIZEBOX
|
WS_SYSMENU, CW_USEDEFAULT,
//
At this point we do not want to
0
,
//
show the window until we know
0
,
//
how big the Dialog Box is so
0
,
//
that we can fit the main window
NULL,
//
around it.
NULL, hInstance, NULL); hDlgMain
=
CreateDialog(hInst, MAKEINTRESOURCE(IDD_PRINT), hWnd, PrintDlgProc); ShowWindow(hWnd, nCmdShow); ShowWindow(hDlgMain, SW_SHOW);
while
(GetMessage(
&
msg, NULL,
0
,
0
)) {
//
Get Next message in queue
if
(hDlgMain
==
NULL
||
!
IsDialogMessage(hDlgMain,
&
msg)) { TranslateMessage(
&
msg);
/*
Translate virtual key codes
*/
DispatchMessage(
&
msg);
/*
Dispatches message to window
*/
} }
//
end while
//
Wait for all threads to terminate. The Window will
//
have already disappeared by this point.
for
(index
=
0
; index
<
gNumPrinting; index
++
) { DWORD status;
do
{
//
Wait for thread to terminate
GetExitCodeThread(gPrintJobs[index],
&
status); Sleep(
10
); }
while
(status
==
STILL_ACTIVE); }
//
end for
return
(msg.wParam);
/*
Returns the value from PostQuitMessage
*/
}LRESULT CALLBACK MainWndProc(HWND hWnd, unsigned msg, WPARAM wParam, LPARAM lParam){
switch
(msg) {
case
WM_CREATE:
break
;
case
WM_COMMAND:
switch
(wParam) {
case
IDM_ABOUT: DialogBox(hInst,
"
AboutBox
"
, hWnd, (DLGPROC)About);
break
;
case
IDM_EXIT: PostQuitMessage(
0
);
break
;
default
:
return
(DefWindowProc(hWnd, msg, wParam, lParam)); }
case
WM_SETFOCUS:
//
ensure that the Dialog Box has the focus
SetFocus(hDlgMain);
break
;
case
WM_DESTROY: PostQuitMessage(
0
);
break
;
default
:
return
DefWindowProc(hWnd, msg, wParam, lParam); }
return
0
;}LRESULT CALLBACK PrintDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch
(uMsg) {
case
WM_CLOSE: DestroyWindow(hDlg); hDlgMain
=
NULL;
break
;
case
WM_DESTROY:
return
TRUE;
break
;
case
WM_SHOWBITMAP:
if
(gbmpDisplay) DeleteObject(gbmpDisplay); gDisplayRect
=
*
(RECT
*
)wParam; gbmpDisplay
=
(HBITMAP) lParam; InvalidateRect(hDlgMain, NULL, TRUE);
break
; HANDLE_MSG(hDlg, WM_INITDIALOG, PrintDlg_OnInitDialog); HANDLE_MSG(hDlg, WM_COMMAND, PrintDlg_OnCommand); HANDLE_MSG(hDlg, WM_PAINT, PrintDlg_OnPaint);
default
:
return
(FALSE); }
return
0
;}BOOL PrintDlg_OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam){ RECT rect;
//
Size parent to fit this dialog
GetWindowRect(hwndDlg,
&
rect); SetWindowPos(GetParent(hwndDlg),NULL,
0
,
0
, rect.right
-
rect.left, rect.bottom
-
rect.top
+
GetSystemMetrics(SM_CYMENU)
+
GetSystemMetrics(SM_CYCAPTION), SWP_NOMOVE
|
SWP_NOZORDER);
return
TRUE;}
void
PrintDlg_OnCommand(HWND hDlg,
int
id,HWND hwndCtl, UINT codeNotify){
char
szText[
256
];
switch
(id) {
case
IDC_PRINT: GetDlgItemText(hDlg, IDC_EDIT_TEXT, szText,
256
); PrintText(hDlg, szText);
break
;
case
IDC_DISPLAY: GetDlgItemText(hDlg, IDC_EDIT_TEXT, szText,
256
); PrintToDisplay(hDlg, szText);
break
;
case
IDCANCEL:
case
IDM_EXIT: PostMessage(GetParent(hDlg),WM_DESTROY, (WPARAM)
0
, (LPARAM)
0
); DestroyWindow(hDlgMain); hDlgMain
=
NULL;
break
;
default
:
break
; }}
void
PrintDlg_OnPaint( HWND hwnd ){ PAINTSTRUCT paint; HWND hwndCtrl; HDC hdc; HDC hDcMem; HBITMAP bmpOld; RECT rect; POINT point;
if
(
!
gbmpDisplay)
return
; hwndCtrl
=
GetDlgItem(hwnd, IDC_OUTPUT); hdc
=
BeginPaint(hwnd,
&
paint); GetWindowRect(hwndCtrl,
&
rect); point
=
*
((POINT
*
)
&
rect); ScreenToClient(hwnd,
&
point); hDcMem
=
CreateCompatibleDC(NULL); bmpOld
=
SelectObject(hDcMem, gbmpDisplay);
//
Copy bitmap to screen
MTVERIFY( BitBlt(hdc, point.x
+
10
, point.y
+
40
, gDisplayRect.right
-
gDisplayRect.left, gDisplayRect.bottom
-
gDisplayRect.top, hDcMem, iHeight,
0
, SRCCOPY) ); SelectObject(hDcMem, bmpOld); DeleteDC(hDcMem); EndPaint(hwnd,
&
paint);}
//
//
Asks user which printer to use, then creates
//
background printing thread.
//
void
PrintText(HWND hwndParent,
char
*
pszText){ ThreadPrintInfo
*
pInfo; HANDLE hThread; DWORD dwThreadId;
int
result; DOCINFO docInfo; PRINTDLG dlgPrint;
//
Put up Common Dialog for Printing and get hDC.
memset(
&
dlgPrint,
0
,
sizeof
(PRINTDLG)); dlgPrint.lStructSize
=
sizeof
(PRINTDLG); dlgPrint.hwndOwner
=
hwndParent; dlgPrint.Flags
=
PD_ALLPAGES
|
PD_USEDEVMODECOPIES
|
PD_NOPAGENUMS
|
PD_NOSELECTION
|
PD_RETURNDC; dlgPrint.hInstance
=
hInst;
if
(
!
PrintDlg(
&
dlgPrint))
return
;
//
Initialize Printer device
docInfo.cbSize
=
sizeof
(DOCINFO); docInfo.lpszDocName
=
"
Background Printing Example
"
; docInfo.lpszOutput
=
NULL; docInfo.lpszDatatype
=
NULL; docInfo.fwType
=
0
; result
=
StartDoc(dlgPrint.hDC,
&
docInfo); result
=
StartPage(dlgPrint.hDC); pInfo
=
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof
(ThreadPrintInfo)); pInfo
->
hDlg
=
hwndParent; pInfo
->
hWndParent
=
hwndParent; pInfo
->
hDc
=
dlgPrint.hDC; pInfo
->
bPrint
=
TRUE; strcpy(pInfo
->
szText, pszText); MTVERIFY( hThread
=
CreateThread(NULL,
0
, BackgroundPrintThread, (LPVOID)pInfo,
0
,
&
dwThreadId ));
//
keep track of all background printing threads
gPrintJobs[gNumPrinting
++
]
=
hThread;}
//
//
Shows output on the dialog box.
//
void
PrintToDisplay(HWND hwndParent,
char
*
pszText){ ThreadPrintInfo
*
pInfo; DWORD dwThreadId; HANDLE hThread; pInfo
=
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof
(ThreadPrintInfo)); pInfo
->
hDlg
=
hwndParent; pInfo
->
hWndParent
=
GetDlgItem(hwndParent, IDC_OUTPUT); pInfo
->
hDc
=
GetDC(pInfo
->
hWndParent); pInfo
->
bPrint
=
FALSE; strcpy(pInfo
->
szText, pszText); MTVERIFY( hThread
=
CreateThread(NULL,
0
, BackgroundPrintThread, (LPVOID)pInfo,
0
,
&
dwThreadId ));
//
keep track of all background printing threads
gPrintJobs[gNumPrinting
++
]
=
hThread;}
//
---------------------------------------------------------
//
About Box Handling
//
---------------------------------------------------------
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){
switch
(message) {
case
WM_COMMAND:
if
(LOWORD(wParam)
==
IDOK
||
LOWORD(wParam)
==
IDCANCEL) { EndDialog(hDlg, TRUE);
return
(TRUE); }
break
;
default
:
return
(DefWindowProc(hDlg, message, wParam, lParam)); }
return
FALSE;}
//
---------------------------------------------------------
//
Background Printing Code
//
---------------------------------------------------------
DWORD WINAPI BackgroundPrintThread(LPVOID pVoid){ ThreadPrintInfo
*
pInfo
=
(ThreadPrintInfo
*
) pVoid; RECT rect; RECT rectMem; HDC hDcMem; HBITMAP bmpMem; HBITMAP bmpOld;
int
x, y;
int
counter
=
0
;
int
nHeight; HFONT hFont; HFONT hFontOld;
//
Get dimensions of paper into rect
rect.left
=
0
; rect.top
=
0
; rect.right
=
GetDeviceCaps(pInfo
->
hDc, HORZRES); rect.bottom
=
GetDeviceCaps(pInfo
->
hDc, VERTRES); nHeight
=
-
MulDiv(
36
, GetDeviceCaps(pInfo
->
hDc, LOGPIXELSY),
72
);
//
Create Font
hFont
=
CreateFont(nHeight,
0
,
0
,
0
, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH, NULL); MTASSERT( hFont
!=
0
);
//
Draw into memory device context
hDcMem
=
CreateCompatibleDC(pInfo
->
hDc); hFontOld
=
SelectObject(hDcMem, hFont); iHeight
=
DrawText(hDcMem, pInfo
->
szText,
-
1
,
&
rect, DT_LEFT
|
DT_NOPREFIX
|
DT_WORDBREAK
|
DT_CALCRECT); rectMem
=
rect; rectMem.left
=
rect.left
+
iHeight; rectMem.right
=
rect.right
+
(iHeight
*
2
); bmpMem
=
CreateCompatibleBitmap(hDcMem, rectMem.right, rect.bottom); bmpOld
=
SelectObject(hDcMem, bmpMem); OffsetRect(
&
rect, iHeight,
0
); DrawText(hDcMem, pInfo
->
szText,
-
1
,
&
rect, DT_LEFT
|
DT_NOPREFIX
|
DT_WORDBREAK);
//
Italicize bitmap. We use GetPixel and
//
SetPixel because they are horribly inefficient,
//
thereby causing the thread to run for awhile.
for
(y
=
0
; y
<
iHeight; y
++
) {
//
Italicize line y
for
(x
=
rectMem.right; x
>
iHeight; x
--
) {
//
Move specified pixel to the right.
COLORREF color;
int
offset; offset
=
y
-
iHeight; color
=
GetPixel(hDcMem, x
+
offset, y);
if
(color
!=
0
) counter
++
; SetPixel(hDcMem, x, y, color); }
//
end for x
}
//
end for y
MTASSERT( counter
>
0
);
//
Copy bitmap of italicized text from memory to device
if
(pInfo
->
bPrint) { BitBlt(pInfo
->
hDc,
50
,
50
, rectMem.right
-
rect.left, rectMem.bottom
-
rect.top, hDcMem, iHeight,
0
, SRCCOPY); } SelectObject(hDcMem, hFontOld); SelectObject(hDcMem, bmpOld); DeleteDC(hDcMem);
if
(
!
pInfo
->
bPrint) {
//
We can't just write to the global variable where the
//
bitmap is kept or we might overwrite the work of
//
another thread, thereby "losing" a bitmap
//
Also, if we used PostMessage instead of SendMessage, then
//
the rectangle could have been deleted (it's on the stack)
//
by the time the main message loop is reached.
SendMessage(pInfo
->
hDlg, WM_SHOWBITMAP, (WPARAM)
&
rectMem, (LPARAM) bmpMem); }
if
(pInfo
->
bPrint) {
//
Finish printing
int
result; result
=
EndPage(pInfo
->
hDc); MTASSERT (result
!=
SP_ERROR); result
=
EndDoc(pInfo
->
hDc); MTASSERT (result
!=
SP_ERROR); DeleteDC(pInfo
->
hDc);
//
If we are printing, we are done with the bitmap.
DeleteObject(bmpMem); }
else
{ ReleaseDC(pInfo
->
hWndParent, pInfo
->
hDc); }
//
free data structure passed in.
HeapFree(GetProcessHeap(),
0
, pInfo);
return
0
;}
od
display
004014A0 /$ A1 20994000 mov eax, dword ptr [409920]004014A5 |. 81EC 60020000 sub esp, 260004014AB |. 85C0 test eax, eax004014AD |. 55 push ebp004014AE |. 56 push esi004014AF |. 57 push edi004014B0 |. 0F84 48010000 je 004015FE004014B6 |. 8BBC24 700200>mov edi, dword ptr [esp+270]004014BD |. 53 push ebx004014BE |. 68 E9030000 push 3E9 ; /ControlID = 3E9 (1001.)004014C3 |. 57 push edi ; |hWnd004014C4 |. FF15 14614000 call dword ptr [<&USER32.GetDlgItem>] ; \GetDlgItem004014CA |. 8BF0 mov esi, eax004014CC |. 8D4424 2C lea eax, dword ptr [esp+2C]004014D0 |. 50 push eax ; /pPaintstruct004014D1 |. 57 push edi ; |hWnd004014D2 |. FF15 18614000 call dword ptr [<&USER32.BeginPaint>] ; \BeginPaint004014D8 |. 8D4C24 1C lea ecx, dword ptr [esp+1C]004014DC |. 8BD8 mov ebx, eax004014DE |. 51 push ecx ; /pRect004014DF |. 56 push esi ; |hWnd004014E0 |. FF15 34614000 call dword ptr [<&USER32.GetWindowRec>; \GetWindowRect004014E6 |. 8B5424 1C mov edx, dword ptr [esp+1C]004014EA |. 8B4424 20 mov eax, dword ptr [esp+20]004014EE |. 8D4C24 14 lea ecx, dword ptr [esp+14]004014F2 |. 895424 14 mov dword ptr [esp+14], edx004014F6 |. 51 push ecx ; /pPoint004014F7 |. 57 push edi ; |hWnd004014F8 |. 894424 20 mov dword ptr [esp+20], eax ; |004014FC |. FF15 1C614000 call dword ptr [<&USER32.ScreenToClie>; \ScreenToClient00401502 |. 6A 00 push 0 ; /hDC = NULL00401504 |. FF15 24604000 call dword ptr [<&GDI32.CreateCompati>; \CreateCompatibleDC0040150A |. 8B15 20994000 mov edx, dword ptr [409920]00401510 |. 8B2D 00604000 mov ebp, dword ptr [<&GDI32.SelectOb>; GDI32.SelectObject00401516 |. 8BF0 mov esi, eax00401518 |. 52 push edx ; /hObject => 7F05063100401519 |. 56 push esi ; |hDC0040151A |. FFD5 call ebp ; \SelectObject0040151C |. 8B0D 1C984000 mov ecx, dword ptr [40981C]00401522 |. 894424 10 mov dword ptr [esp+10], eax00401526 |. A1 2C994000 mov eax, dword ptr [40992C]0040152B |. 68 2000CC00 push 0CC0020 ; /ROP = SRCCOPY00401530 |. 8B15 18984000 mov edx, dword ptr [409818] ; |00401536 |. 6A 00 push 0 ; |YSrc = 000401538 |. 50 push eax ; |XSrc => 37 (55.)00401539 |. A1 14984000 mov eax, dword ptr [409814] ; |0040153E |. 2BC8 sub ecx, eax ; |00401540 |. 8B4424 24 mov eax, dword ptr [esp+24] ; |00401544 |. 56 push esi ; |hSrcDC00401545 |. 51 push ecx ; |Height00401546 |. 8B0D 10984000 mov ecx, dword ptr [409810] ; |0040154C |. 83C0 28 add eax, 28 ; |0040154F |. 2BD1 sub edx, ecx ; |00401551 |. 8B4C24 28 mov ecx, dword ptr [esp+28] ; |00401555 |. 52 push edx ; |Width00401556 |. 83C1 0A add ecx, 0A ; |00401559 |. 50 push eax ; |YDest0040155A |. 51 push ecx ; |XDest0040155B |. 53 push ebx ; |hDestDC0040155C |. FF15 28604000 call dword ptr [<&GDI32.BitBlt>] ; \BitBlt00401562 |. 85C0 test eax, eax00401564 |. 5B pop ebx00401565 |. 75 7C jnz short 004015E300401567 |. FF15 D8604000 call dword ptr [<&KERNEL32.GetLastErr>; [GetLastError0040156D |. 6A 00 push 0 ; /Arguments = NULL0040156F |. 8D5424 10 lea edx, dword ptr [esp+10] ; |00401573 |. 6A 00 push 0 ; |BufSize = 000401575 |. 52 push edx ; |Buffer00401576 |. 6A 00 push 0 ; |LanguageId = 0 (LANG_NEUTRAL)00401578 |. 50 push eax ; |MessageId00401579 |. 6A 00 push 0 ; |pSource = NULL0040157B |. 68 00110000 push 1100 ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|000401580 |. FF15 DC604000 call dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA00401586 |. 8B4424 0C mov eax, dword ptr [esp+C]0040158A |. 8D4C24 68 lea ecx, dword ptr [esp+68]0040158E |. 50 push eax ; /<%s>0040158F |. 68 C8704000 push 004070C8 ; |<%s> = "BitBlt(hdc, point.x+10, point.y+40, gDisplayRect.right-gDisplayRect.left, gDisplayRect.bottom-gDisplayRect.top, hDcMem, iHeight, 0, SRCCOPY)"00401594 |. 68 BC704000 push 004070BC ; |<%s> = "BackPrnt.c"00401599 |. 68 25010000 push 125 ; |<%d> = 125 (293.)0040159E |. 68 78704000 push 00407078 ; |Format = LF,"The following call failed at line %d in %s:",LF,LF," %s",LF,LF,"Reason: %s",LF,""004015A3 |. 51 push ecx ; |s004015A4 |. FF15 20614000 call dword ptr [<&USER32.wsprintfA>] ; \wsprintfA004015AA |. 83C4 18 add esp, 18004015AD |. 8D9424 680100>lea edx, dword ptr [esp+168]004015B4 |. 68 04010000 push 104 ; /BufSize = 104 (260.)004015B9 |. 52 push edx ; |PathBuffer004015BA |. 6A 00 push 0 ; |hModule = NULL004015BC |. FF15 E0604000 call dword ptr [<&KERNEL32.GetModuleF>; \GetModuleFileNameA004015C2 |. 8D8424 680100>lea eax, dword ptr [esp+168]004015C9 |. 68 30200100 push 12030 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL|10000004015CE |. 8D4C24 6C lea ecx, dword ptr [esp+6C] ; |004015D2 |. 50 push eax ; |Title004015D3 |. 51 push ecx ; |Text004015D4 |. 6A 00 push 0 ; |hOwner = NULL004015D6 |. FF15 24614000 call dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA004015DC |. 6A 01 push 1004015DE |. E8 A0050000 call 00401B83004015E3 |> 8B5424 0C mov edx, dword ptr [esp+C]004015E7 |. 52 push edx004015E8 |. 56 push esi004015E9 |. FFD5 call ebp004015EB |. 56 push esi ; /hDC004015EC |. FF15 2C604000 call dword ptr [<&GDI32.DeleteDC>] ; \DeleteDC004015F2 |. 8D4424 28 lea eax, dword ptr [esp+28]004015F6 |. 50 push eax ; /pPaintstruct004015F7 |. 57 push edi ; |hWnd004015F8 |. FF15 28614000 call dword ptr [<&USER32.EndPaint>] ; \EndPaint004015FE |> 5F pop edi004015FF |. 5E pop esi00401600 |. 5D pop ebp00401601 |. 81C4 60020000 add esp, 26000401607 \. C3 retn
print
转载于:https://www.cnblogs.com/nanshouyong326/archive/2010/07/08/1773432.html