簡體   English   中英

控制台事件處理不像假定的 C++ 那樣工作

[英]Console eventhandling doesn`t work like supposed c++

我有一個問題,即使用DWORD CEvent參數的意外值調用定義的函數consoleHandler() ,因此switch語句永遠不會與定義的情況匹配,只會調用default

CEvent總是一些奇怪的隨機數。 如果我打印出CRTL_CLOSE_EVENT ,我會得到CEvent永遠不會是 2,即使我用鼠標關閉窗口也是如此。

怎么了? 類型轉換有問題嗎?

class Runner {

    bool isRunning = false;

public:

    void reevoke(){
        char p[] = "path to exe";
        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );

        CreateProcess(p ,   // the path
                      NULL,        // Command line
                      NULL,           // Process handle not inheritable
                      NULL,           // Thread handle not inheritable
                      FALSE,          // Set handle inheritance to FALSE
                      0,              // No creation flags
                      NULL,           // Use parent's environment block
                      NULL,           // Use parent's starting directory
                      &si,            // Pointer to STARTUPINFO structure
                      &pi             // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
        );
    }

    BOOL WINAPI ConsoleHandler(DWORD CEvent)
    {
        cout << CEvent << " | " <<  CTRL_CLOSE_EVENT <<endl;

        switch(CEvent)
        {
            /*case CTRL_CLOSE_EVENT:
                MessageBox(NULL,
                           "CTRL+BREAK received!","CEvent",MB_OK);
                cout << "closed bbbb"<<endl;
                this->reevoke();
                break;*/

            case CTRL_C_EVENT:
                this->reevoke();
                return TRUE;

            case CTRL_CLOSE_EVENT:
                Beep(600, 200);
                printf("Ctrl-Close event\n\n");
                return TRUE;

            default:
                 cout << "Event was: " << CEvent  <<endl;
        }

        return TRUE;
    }

    ~Runner()
    {
        if(GetKeyState('Q') & 0x8000){
            cout << "q pressed" << endl;
        }
        else{
            if(SetConsoleCtrlHandler(
                (PHANDLER_ROUTINE)&ConsoleHandler, // handler function
                TRUE // add or remove handler
            ) == FALSE){
                cout << "could not set Handler" << endl;
            }
            else{
                cout << "Handler Set" << endl;
                Sleep(1000);
            }

            while (1) {}

            cout << "constructor called" << endl;
        }
    }
};

int main()
{
    cout << "Hello world! I am unstoppable" << endl;
    Runner r;
    return 0;
}

您的ConsoleHandler()是一個非靜態類方法。 必須在Runner的對象實例上調用它。

這意味着,您不能將其用作 Win32 API 回調。 它有一個隱藏的this參數,API 不知道,因此無法將Runner對象地址傳遞給。

您強制ConsoleHandler()作為回調的類型轉換正在調用未定義的行為,這就是CEvent參數未接收到正確值的原因。 它從錯誤的內存位置接收它的值。

如果您放棄類型轉換,這段代碼將無法編譯是有充分理由的。 只有獨立函數和靜態類方法可以用作 Win32 API 回調。 不要使用類型轉換來消除編譯器錯誤。 改為修復錯誤。

試試這個:

class Runner {
public:
    static void reevoke(){
        char p[] = "path to exe";
        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );

        if (CreateProcess(p,              // the path
                          NULL,           // Command line
                          NULL,           // Process handle not inheritable
                          NULL,           // Thread handle not inheritable
                          FALSE,          // Set handle inheritance to FALSE
                          0,              // No creation flags
                          NULL,           // Use parent's environment block
                          NULL,           // Use parent's starting directory
                          &si,            // Pointer to STARTUPINFO structure
                          &pi             // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
            ))
        {
            CloseHandle(pi.hThread);
            CloseHandle(pi.hProcess);
        }
    }

    static BOOL WINAPI ConsoleHandler(DWORD CEvent)
    {
        cout << CEvent << " | " <<  CTRL_CLOSE_EVENT << endl;

        switch (CEvent)
        {
            case CTRL_CLOSE_EVENT:
                Beep(600, 200);
                MessageBox(NULL,
                           "CTRL+BREAK received!",
                           "CEvent",
                           MB_OK);
                cout << "closed bbbb" << endl;
                reevoke();
                break;

            case CTRL_C_EVENT:
                reevoke();
                return TRUE;

            default:
                 cout << "Event was: " << CEvent << endl;
        }

        return TRUE;
    }

    ~Runner()
    {
        cout << "destructor called" << endl;
        if (GetKeyState('Q') & 0x8000){
            cout << "q pressed" << endl;
        }
        else if (SetConsoleCtrlHandler(&ConsoleHandler, TRUE) == FALSE){
            cout << "could not set Handler" << endl;
        }
        else{
            cout << "Handler Set" << endl;
            Sleep(1000);

            while (1) {}
        }
    }
};

int main()
{
    cout << "Hello world! I am unstoppable" << endl;
    Runner r;
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM