CodeExplorer Posted February 2, 2019 Posted February 2, 2019 Sending Alt+Pause (Alt+Break) to dosbox debugger ??? DosBox uses SDL.dll so I think SendInput function has to be used: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendinput SendInputExamples: https://batchloaf.wordpress.com/2012/04/17/simulating-a-keystroke-in-win32-c-or-c-using-sendinput/ https://stackoverflow.com/questions/6811899/how-would-i-use-keybd-event-to-send-a-for-example https://batchloaf.wordpress.com/2012/10/18/simulating-a-ctrl-v-keystroke-in-win32-c-or-c-using-sendinput/ https://stackoverflow.com/questions/29129987/c-simulating-keystrokes-using-sendinput-method-failure-to-distinguish-right Anyway Visual C++ 6.0 compiler complains about INPUT structure not being found: INPUT structure is defined here: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taginput How to fix it?
CodeExplorer Posted February 2, 2019 Author Posted February 2, 2019 For INPUT thing I've defined on first line of StdAfx.h #define _WIN32_WINNT 0x0500 // so the code would compile I get the answer from: http://answers.google.com/answers/threadview?id=359697 and now https://batchloaf.wordpress.com/2012/04/17/simulating-a-keystroke-in-win32-c-or-c-using-sendinput/ will compile but still doesn't send the key to dosbox console!
CodeExplorer Posted February 2, 2019 Author Posted February 2, 2019 SendInput acts in the same way with: keybd_event('A', 0, 0, 0); keybd_event('A', 0, KEYEVENTF_KEYUP, 0); I found that after executing the code the key is send to the program who made the call to keybd_event and not the program I wanted even if I set to foreground using: HWND w_handle = GetMainWindowHandle(GetPid()); ::SetForegroundWindow(w_handle); SendMessage Api won't work at all for this program! I only could think of CreateRemoteThread(keybd_event)!
CodeExplorer Posted February 2, 2019 Author Posted February 2, 2019 I've looked a bit to DOSBOX source code: https://sourceforge.net/p/dosbox/code-0/HEAD/tree/ /* Non-focus priority is set to pause; check to see if we've lost window or input focus * i.e. has the window been minimised or made inactive? */ if (sdl.priority.nofocus == PRIORITY_LEVEL_PAUSE) { if ((event.active.state & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) && (!event.active.gain)) { /* Window has lost focus, pause the emulator. * This is similar to what PauseDOSBox() does, but the exit criteria is different. * Instead of waiting for the user to hit Alt-Break, we wait for the window to * regain window or input focus. */ bool paused = true; SDL_Event ev; GFX_SetTitle(-1,-1,true); KEYBOARD_ClrBuffer(); // SDL_Delay(500); // while (SDL_PollEvent(&ev)) { // flush event queue. // } while (paused) { // WaitEvent waits for an event rather than polling, so CPU usage drops to zero SDL_WaitEvent(&ev); switch (ev.type) { case SDL_QUIT: throw(0); break; // a bit redundant at linux at least as the active events gets before the quit event. case SDL_ACTIVEEVENT: // wait until we get window focus back if (ev.active.state & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) { // We've got focus back, so unpause and break out of the loop if (ev.active.gain) { paused = false; GFX_SetTitle(-1,-1,false); } /* Now poke a "release ALT" command into the keyboard buffer * we have to do this, otherwise ALT will 'stick' and cause * problems with the app running in the DOSBox. */ KEYBOARD_AddKey(KBD_leftalt, false); KEYBOARD_AddKey(KBD_rightalt, false); } break; } } } } And the method PauseDOSBox: static void PauseDOSBox(bool pressed) { if (!pressed) return; GFX_SetTitle(-1,-1,true); bool paused = true; KEYBOARD_ClrBuffer(); SDL_Delay(500); SDL_Event event; while (SDL_PollEvent(&event)) { // flush event queue. } while (paused) { SDL_WaitEvent(&event); // since we're not polling, cpu usage drops to 0. switch (event.type) { case SDL_QUIT: KillSwitch(true); break; case SDL_KEYDOWN: // Must use Pause/Break Key to resume. case SDL_KEYUP: if(event.key.keysym.sym == SDLK_PAUSE) { paused = false; GFX_SetTitle(-1,-1,false); break; } #if defined (MACOSX) if (event.key.keysym.sym == SDLK_q && (event.key.keysym.mod == KMOD_RMETA || event.key.keysym.mod == KMOD_LMETA) ) { /* On macs, all aps exit when pressing cmd-q */ KillSwitch(true); break; } #endif } } } My guess is that: if(event.key.keysym.sym == SDLK_PAUSE) is the Alt+Pause key!
CodeExplorer Posted February 3, 2019 Author Posted February 3, 2019 (edited) Found a solution that works: https://www.codeproject.com/Articles/6819/SendKeys-in-C Still working at it. The sleep part is important! Edit: found a way: HWND w_handle = GetMainWindowHandle(GetPid()); CSendKeys sk; sk.AppActivate(w_handle); //Send "Hello world!" sk.SendKeys("{DELAY=22}%{BREAK}"); sk.SendKeys("{DELAY=22}%{BREAK}"); Edited February 3, 2019 by CodeExplorer
CodeExplorer Posted February 3, 2019 Author Posted February 3, 2019 When I am not debugging all works ok. Now what I want to do is set breakpoint on read and when the breakpoint is reached press Alt+Pause: also break DOS box debugger: unfortunately doesn't work; int process_id = GetPid(); if (process_id<0) return; HardwareBreakpoint bp; int ThreadID = 0; m_logs1.SetLimitText(0); UINT limit = m_logs1.GetLimitText(); //The current text limit, in bytes, for this CEdit object. if (RegisterHotKey( NULL, 1, MOD_ALT, // | MOD_NOREPEAT 0x43)) //0x43 is 'C' { _tprintf(_T("Hotkey 'ALT+C' registered!\n")); } if (DebugActiveProcess(process_id)) { bool ss=true; DEBUG_EVENT DE={0}; while(ss) { WaitForDebugEvent(&DE,INFINITE); LogString(GetDebugEventName(DE.dwDebugEventCode)); switch(DE.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: { ThreadID = DE.dwThreadId; func OpenThread=(func)GetProcAddress(GetModuleHandle("KERNEL32.dll"), "OpenThread"); HANDLE threadhandle = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, 0, DE.dwThreadId); char txt[10]; GetDlgItemText(IDC_EDIT1, txt, 10); long break_address = strtol(txt, 0, 16); bool set_ok = bp.Set(threadhandle, (DWORD)(break_address), 4, HardwareBreakpoint::Read); break; // 00403010 } // //ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_EXCEPTION_NOT_HANDLED); case EXIT_PROCESS_DEBUG_EVENT: ss=false; break; case EXCEPTION_DEBUG_EVENT: { EXCEPTION_DEBUG_INFO& exception = DE.u.Exception; switch( exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_SINGLE_STEP: // Same value as EXCEPTION_BREAKPOINT Beep( 750, 300 ); LogString("Single step"); MSG msg = {0}; while (GetMessage(&msg, NULL, 0, 0) != 0) { if (msg.message == WM_HOTKEY) { ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_CONTINUE); break; } } break; } ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_EXCEPTION_NOT_HANDLED); } } ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_CONTINUE); } } } This is the code I'm using When I do "sk.AppActivate(w_handle);" which does the fallowing: bool CSendKeys::AppActivate(HWND wnd) { if (wnd == NULL) return false; ::SendMessage(wnd, WM_SYSCOMMAND, SC_HOTKEY, (LPARAM) wnd); ::SendMessage(wnd, WM_SYSCOMMAND, SC_RESTORE, (LPARAM) wnd); ::ShowWindow(wnd, SW_SHOW); ::SetForegroundWindow(wnd); ::SetFocus(wnd); return true; } my created program stucks! Any way I could fix this?
CodeExplorer Posted February 4, 2019 Author Posted February 4, 2019 (edited) Found https://sourceforge.net/p/dosbox/code-0/HEAD/tree/dosbox/trunk/src/gui/sdlmain.cpp#l1481 #if C_DEBUG /* Pause binds with activate-debugger */ #else MAPPER_AddHandler(&PauseDOSBox, MK_pause, MMOD2, "pause", "Pause DBox"); #endif And found SSL library https://libsdl.org/download-2.0.php I couldn't find the "Pause DBox" string in compiled exes. Found the reason: different DOSBOX version; here is https://sourceforge.net/p/dosbox/code-0/2257/tree/dosbox/trunk/src/gui/sdlmain.cpp#l913 Edited February 4, 2019 by CodeExplorer
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now