2-6

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, 0sizeof(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, 00))
    {    
// 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, 0sizeof(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
        
00, 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, 5050, 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, 260
004014AB  |.  85C0          test    eax, eax
004014AD  |.  55            push    ebp
004014AE  |.  56            push    esi
004014AF  |.  57            push    edi
004014B0  |.  0F84 48010000 je      004015FE
004014B6  |.  8BBC24 700200>mov     edi, dword ptr [esp+270]
004014BD  |.  53            push    ebx
004014BE  |.  68 E9030000   push    3E9                              ; /ControlID = 3E9 (1001.)
004014C3  |.  57            push    edi                              ; |hWnd
004014C4  |.  FF15 14614000 call    dword ptr [<&USER32.GetDlgItem>] ; \GetDlgItem
004014CA  |.  8BF0          mov     esi, eax
004014CC  |.  8D4424 2C     lea     eax, dword ptr [esp+2C]
004014D0  |.  50            push    eax                              ; /pPaintstruct
004014D1  |.  57            push    edi                              ; |hWnd
004014D2  |.  FF15 18614000 call    dword ptr [<&USER32.BeginPaint>] ; \BeginPaint
004014D8  |.  8D4C24 1C     lea     ecx, dword ptr [esp+1C]
004014DC  |.  8BD8          mov     ebx, eax
004014DE  |.  51            push    ecx                              ; /pRect
004014DF  |.  56            push    esi                              ; |hWnd
004014E0  |.  FF15 34614000 call    dword ptr [<&USER32.GetWindowRec>; \GetWindowRect
004014E6  |.  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], edx
004014F6  |.  51            push    ecx                              ; /pPoint
004014F7  |.  57            push    edi                              ; |hWnd
004014F8  |.  894424 20     mov     dword ptr [esp+20], eax          ; |
004014FC  |.  FF15 1C614000 call    dword ptr [<&USER32.ScreenToClie>; \ScreenToClient
00401502  |.  6A 00         push    0                                ; /hDC = NULL
00401504  |.  FF15 24604000 call    dword ptr [<&GDI32.CreateCompati>; \CreateCompatibleDC
0040150A  |.  8B15 20994000 mov     edx, dword ptr [409920]
00401510  |.  8B2D 00604000 mov     ebp, dword ptr [<&GDI32.SelectOb>;  GDI32.SelectObject
00401516  |.  8BF0          mov     esi, eax
00401518  |.  52            push    edx                              ; /hObject => 7F050631
00401519  |.  56            push    esi                              ; |hDC
0040151A  |.  FFD5          call    ebp                              ; \SelectObject
0040151C  |.  8B0D 1C984000 mov     ecx, dword ptr [40981C]
00401522  |.  894424 10     mov     dword ptr [esp+10], eax
00401526  |.  A1 2C994000   mov     eax, dword ptr [40992C]
0040152B  |.  68 2000CC00   push    0CC0020                          ; /ROP = SRCCOPY
00401530  |.  8B15 18984000 mov     edx, dword ptr [409818]          ; |
00401536  |.  6A 00         push    0                                ; |YSrc = 0
00401538  |.  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                              ; |hSrcDC
00401545  |.  51            push    ecx                              ; |Height
00401546  |.  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                              ; |Width
00401556  |.  83C1 0A       add     ecx, 0A                          ; |
00401559  |.  50            push    eax                              ; |YDest
0040155A  |.  51            push    ecx                              ; |XDest
0040155B  |.  53            push    ebx                              ; |hDestDC
0040155C  |.  FF15 28604000 call    dword ptr [<&GDI32.BitBlt>]      ; \BitBlt
00401562  |.  85C0          test    eax, eax
00401564  |.  5B            pop     ebx
00401565  |.  75 7C         jnz     short 004015E3
00401567  |.  FF15 D8604000 call    dword ptr [<&KERNEL32.GetLastErr>; [GetLastError
0040156D  |.  6A 00         push    0                                ; /Arguments = NULL
0040156F  |.  8D5424 10     lea     edx, dword ptr [esp+10]          ; |
00401573  |.  6A 00         push    0                                ; |BufSize = 0
00401575  |.  52            push    edx                              ; |Buffer
00401576  |.  6A 00         push    0                                ; |LanguageId = 0 (LANG_NEUTRAL)
00401578  |.  50            push    eax                              ; |MessageId
00401579  |.  6A 00         push    0                                ; |pSource = NULL
0040157B  |.  68 00110000   push    1100                             ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|0
00401580  |.  FF15 DC604000 call    dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA
00401586  |.  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                              ; |s
004015A4  |.  FF15 20614000 call    dword ptr [<&USER32.wsprintfA>]  ; \wsprintfA
004015AA  |.  83C4 18       add     esp, 18
004015AD  |.  8D9424 680100>lea     edx, dword ptr [esp+168]
004015B4  |.  68 04010000   push    104                              ; /BufSize = 104 (260.)
004015B9  |.  52            push    edx                              ; |PathBuffer
004015BA  |.  6A 00         push    0                                ; |hModule = NULL
004015BC  |.  FF15 E0604000 call    dword ptr [<&KERNEL32.GetModuleF>; \GetModuleFileNameA
004015C2  |.  8D8424 680100>lea     eax, dword ptr [esp+168]
004015C9  |.  68 30200100   push    12030                            ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL|10000
004015CE  |.  8D4C24 6C     lea     ecx, dword ptr [esp+6C]          ; |
004015D2  |.  50            push    eax                              ; |Title
004015D3  |.  51            push    ecx                              ; |Text
004015D4  |.  6A 00         push    0                                ; |hOwner = NULL
004015D6  |.  FF15 24614000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
004015DC  |.  6A 01         push    1
004015DE  |.  E8 A0050000   call    00401B83
004015E3  |>  8B5424 0C     mov     edx, dword ptr [esp+C]
004015E7  |.  52            push    edx
004015E8  |.  56            push    esi
004015E9  |.  FFD5          call    ebp
004015EB  |.  56            push    esi                              ; /hDC
004015EC  |.  FF15 2C604000 call    dword ptr [<&GDI32.DeleteDC>]    ; \DeleteDC
004015F2  |.  8D4424 28     lea     eax, dword ptr [esp+28]
004015F6  |.  50            push    eax                              ; /pPaintstruct
004015F7  |.  57            push    edi                              ; |hWnd
004015F8  |.  FF15 28614000 call    dword ptr [<&USER32.EndPaint>]   ; \EndPaint
004015FE  |>  5F            pop     edi
004015FF  |.  5E            pop     esi
00401600  |.  5D            pop     ebp
00401601  |.  81C4 60020000 add     esp, 260
00401607  \.  C3            retn

 

 

print

 

 

posted @ 2010-07-08 11:27  南守拥  阅读(269)  评论(0编辑  收藏  举报