WinAPI:互斥体不是特定代码中的静音

时间:2017-06-07 23:42:54

标签: c winapi

我完全没理解这个的原因。当我编译并运行它时,程序会不断打开打印机选择对话框。我知道我可能会误解一些东西,但我尽管我至少可以通过互斥锁防止这种情况,为什么互斥锁不会阻止多线程执行? PrintDlgEx是一个阻塞程序,我确认有多个线程(????)运行调试输出。好的代码只有在前一个关闭之后才会打开打印对话框。

以下代码运行5秒左右的典型输出是:

168
called pdx
called pdx
168
pdx returned
HRES 0
pdx returned
HRES 0

肯定意味着有多个线程正在运行但是我没有在ProcessExplorer中看到这些线程。一个线程如何运行WndProc的多个实例?

因此,在指出互斥锁是线程拥有的之后,现在真正的问题可能就是为什么有WndProc多个实例在运行?

#include <windows.h>
#include <stdio.h>

HANDLE ghMutex=NULL;

enum hotkey {
    bESC
};


static LRESULT CALLBACK WndProc(
    HWND hwnd,        // handle to window
    UINT uMsg,        // message identifier
    WPARAM wParam,    // first message parameter
    LPARAM lParam)    // second message parameter
{

    static enum class mode {init,signal,noise,search} Mode;
    static HRESULT hResult;
    static PRINTDLGEX pdx;
    static LPPRINTPAGERANGE pPageRanges = NULL;
    static enum class status {printing, stopped} Status;
    static int jobId;
    static HANDLE printerHd;
    JOB_INFO_1A *JobInfo1;

    static bool inited;

    if(ghMutex==NULL){
        ghMutex = CreateMutex( 
            NULL,              // default security attributes
            FALSE,             // initially not owned
            NULL);             // unnamed mutex
        printf("%d\n",(int)ghMutex);
        if(ghMutex==NULL) return 0;
    }

    if(WaitForSingleObject( 
        ghMutex,
        INFINITE)!=WAIT_OBJECT_0) return 0;

    switch (uMsg) 
    {
        case WM_TIMER:
            {
                if(!inited) {
                    pdx = PRINTDLGEX{0};
                    pPageRanges = NULL;

                    // Allocate an array of PRINTPAGERANGE structures.
                    pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
                    if (!pPageRanges)
                        break;

                    //  Initialize the PRINTDLGEX structure.
                    pdx.lStructSize = sizeof(PRINTDLGEX);
                    pdx.hwndOwner = GetDesktopWindow();
                    pdx.hDevMode = NULL;
                    pdx.hDevNames = NULL;
                    pdx.hDC = NULL;
                    pdx.Flags = PD_RETURNDC | PD_COLLATE | PD_NOPAGENUMS;
                    pdx.Flags2 = 0;
                    pdx.ExclusionFlags = 0;
                    pdx.nPageRanges = 0;
                    pdx.nMaxPageRanges = 10;
                    pdx.lpPageRanges = pPageRanges;
                    pdx.nMinPage = 1;
                    pdx.nMaxPage = 1000;
                    pdx.nCopies = 1;
                    pdx.hInstance = 0;
                    pdx.lpPrintTemplateName = NULL;
                    pdx.lpCallback = NULL;
                    pdx.nPropertyPages = 0;
                    pdx.lphPropertyPages = NULL;
                    pdx.nStartPage = START_PAGE_GENERAL;
                    pdx.dwResultAction = 0;

                    //  Invoke the Print property sheet.

                    printf("called pdx\n");
                    hResult = PrintDlgEx(&pdx);
                    printf("pdx returned\n");
                    inited=1;
                }
                printf("HRES %d\n",(int)hResult);
                if ((hResult == S_OK) && pdx.dwResultAction == PD_RESULT_PRINT) 
                {
                    // User clicked the Print button, so use the DC and other information returned in the 
                    // PRINTDLGEX structure to print the document.

                    int ph=GetDeviceCaps(pdx.hDC,PHYSICALHEIGHT);
                    int pw=GetDeviceCaps(pdx.hDC,PHYSICALWIDTH);
                    int offX=GetDeviceCaps(pdx.hDC,PHYSICALOFFSETX);
                    int offY=GetDeviceCaps(pdx.hDC,PHYSICALOFFSETY);

                    int dimX=pw-2*offX;
                    int dimY=ph-2*offY;


                    DOCINFOA nao{sizeof(DOCINFOA),"test",NULL,NULL,0};

                    jobId=StartDoc(pdx.hDC,&nao);
                    StartPage(pdx.hDC);
        ////////////nothing
                    EndPage(pdx.hDC);
                    EndDoc(pdx.hDC);
                }

            } break;
        case WM_CREATE: 
            // Initialize the window. 
            {
                inited=false;
                SetTimer(hwnd,1,2500,NULL);
            }
            break;

        case WM_DESTROY: 
            // Clean up window-specific data objects.
            {
                CloseHandle(ghMutex);
                ghMutex=NULL;
            }
            SendMessage(hwnd,WM_USER+1,0,0);
            break;

        case WM_HOTKEY:
            {
                DestroyWindow(hwnd);
            }
            break;
        // 
        // Process other messages. 
        // 
        default: 
            ReleaseMutex(ghMutex); return DefWindowProc(hwnd, uMsg, wParam, lParam); 
    } 
    ReleaseMutex(ghMutex);return 0; 
}


void testPrinter()
{

    HWND hwnd;
    {
        WNDCLASSA wc;
        wc.style = CS_HREDRAW | CS_VREDRAW; 
        wc.lpfnWndProc = (WNDPROC) WndProc; 
        wc.cbClsExtra = 0; 
        wc.cbWndExtra = 0; 
        wc.hInstance = GetModuleHandle(NULL); 
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
        wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
        wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); 
        wc.lpszMenuName =  ""; 
        wc.lpszClassName = "PinTest"; 

        if (!RegisterClass(&wc)) 
           return; //cannot register window class

        hwnd=CreateWindowEx(0,"PinTest","topmost print testing window without borders and title bar",WS_VISIBLE|WS_BORDER,0,0,300,300,0,0,0,0);

        RegisterHotKey(hwnd,bESC,0,VK_ESCAPE);
    }


    MSG recent;
    BOOL result;
    while((result=GetMessage(&recent,hwnd,0,0))&&result!=-1) { //bool can be -1 in MS world
        if(recent.message==WM_USER+1) break;
        TranslateMessage(&recent);
        DispatchMessage(&recent);
    }


    return;
}



int main(){
    testPrinter();
}

0 个答案:

没有答案