[英]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.