After spending about two days’ worth of researching about this subject, I was not able to find a single reliable resource describing the console window’s message loop. I found some unreliable ones (they were AI generated) describing vaguely that you could tap into the console window’s message loop, but then precise information on how to do this is lacking everywhere. Anyway, I finally gave up completely when the following code was not able to detect windows messages directed to the console window. I must give credit to Sz about the insularity of the "CSRSS" process.
/*
This is the final work which shows whether it is possible
or not to track messages sent to the command window. All
tests have shown that this is not possible.
15-04-2024
*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam);
char textString[] = "Click this area to create a Console Window";
HWND hConsoleWindow = (HWND)1; // needs to be global
HANDLE ohandle, ihandle; // needs to be global
LPDWORD lpThreadId; // needs to be global (!)
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)
{
HWND hWnd;
MSG lpMsg;
WNDCLASS wndclss;
TCHAR szBuffer[2056];
if(!hPrevInst)
{
wndclss.lpszClassName = "Console Message Test";
wndclss.hInstance = hInst;
wndclss.lpfnWndProc = WndProc;
wndclss.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclss.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclss.lpszMenuName = NULL;
wndclss.hbrBackground = GetStockObject(WHITE_BRUSH);
wndclss.style = 0;
wndclss.cbClsExtra = 0;
wndclss.cbWndExtra = 0;
if(!RegisterClass(&wndclss)) return FALSE;
}
hWnd = CreateWindow("Console Message Test", "Console Message Test",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, NULL,
NULL, hInst, NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&lpMsg, NULL, 0, 0)) // This is the message loop
{
TranslateMessage(&lpMsg);
//hConsoleWindow = FindWindow("ConsoleWindowClass", NULL); // activate this line facultatively, as a test. Might have an effect if no other conole window is open.
/* the above line will terminate the program if no console is present. All this means is that a NULL was returned. */
if(lpMsg.hwnd == hConsoleWindow) return( lpMsg.wParam);
/* (the above line) if any message reaches the console window through this loop, the program closes! */
//if(lpMsg.message == WM_DROPFILES) return( lpMsg.wParam); // activate this line facultatively (as a test)
/* the above line will make the program close if a file is dropped into the white area */
DispatchMessage(&lpMsg);
}
return(lpMsg.wParam);
}
DWORD WINAPI ConsoleThread(LPVOID Param)
{
DWORD dwCount, dwMsgLen;
TCHAR szBuffer[2056];
for(;;){
ReadConsole(ihandle, szBuffer, sizeof(szBuffer) - 2, &dwCount, NULL);
WriteConsole(ohandle, "You typed: ", 11, &dwMsgLen, NULL);
WriteConsole(ohandle, szBuffer, dwCount, &dwMsgLen, NULL);
}
}
// Main Window Procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT pstruct;
static HANDLE hThread = NULL;
switch(messg)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &pstruct);
TextOut(hdc, 0, 0, textString, (sizeof(textString) - 1));
EndPaint(hWnd, &pstruct);
break;
case WM_LBUTTONDOWN:
AllocConsole();
hConsoleWindow = FindWindow("ConsoleWindowClass", NULL);
if(hConsoleWindow) Beep(1000, 250); // high note when console detected
//DragAcceptFiles(hConsoleWindow, TRUE); // this line seems to have no effect
DragAcceptFiles(hWnd,TRUE); /* this line makes the white area accept dragged
objects once it is clicked */
if(hThread == NULL) {
ohandle = GetStdHandle(STD_OUTPUT_HANDLE);
ihandle = GetStdHandle(STD_INPUT_HANDLE);
hThread = CreateThread(NULL, 0, ConsoleThread, NULL, 0, lpThreadId);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_DROPFILES:
Beep(500, 250); // low note when file drop detected
break;
default:
return(DefWindowProc(hWnd, messg, wParam, lParam));
}
return(0);
}
PS I take the OP to refer to XP/Windows Server 2003 era Windows OSes’ command line. Later Windows OSes are different (i.e. multiple items dropped are accepted by default in a console program.)