//================================= // LISTING 1: QUEUE.C // // QUEUE, by Matt Pietrek, 1992 // //================================= #include #include #include "winio.h" // If your IMPORT.LIB or LIBW.LIB doesn't include // GetTaskQueue(), you'll have to add it to the IMPORTS section // of the .DEF file. The ordinal number is KERNEL.35 WORD FAR PASCAL GetTaskQueue(WORD hTask); typedef struct { DWORD extraInfo; HWND hwnd; WORD message; WORD wParam; DWORD lParam; DWORD time; POINT pt; } QUEUEMSG; typedef struct { WORD NextQueue; WORD OwningTask; WORD MessageSize; WORD NumMessages; WORD ReadPtr; WORD WritePtr; WORD Size; LONG MessageTime; POINT MessagePoint; WORD Unknown1; DWORD ExtraInfo; WORD Unknown2; LONG SendMessageLParam; WORD SendMessageWParam; WORD SendMessageMessage; HWND SendMessageHWnd; DWORD SendMessageResult; WORD QuitFlag; int ExitCode; WORD flags; DWORD Unknown3; WORD ExpWinVersion; WORD SendingHQ; WORD sendmsg_helper1; WORD sendmsg_helper2; WORD PaintCount; WORD TimersCount; WORD ChangeBits; WORD WakeBits; WORD WakeMask; WORD SendMessageResult1; WORD SendMessageResult2; WORD SendMessageResult3; WORD Hook; BYTE Hooks2[30]; BYTE MessageArrayStart; } QUEUE; // // Dumps selected fields of a message queue // void DumpQueueContents(QUEUE far *queue) { QUEUEMSG far *queuemsg; unsigned maxMessages, i; maxMessages = ( queue->Size - FP_OFF(&queue->MessageArrayStart)) / sizeof(QUEUEMSG); queuemsg = (QUEUEMSG far *) &queue->MessageArrayStart; printf("Messages: %u ReadPtr: %04X WritePtr: %04X\n", queue->NumMessages, queue->ReadPtr, queue->WritePtr); printf("WakeBits: "); if ( queue->WakeBits & QS_KEY ) printf("QS_KEY "); if ( queue->WakeBits & QS_MOUSE ) printf("QS_MOUSE "); if ( queue->WakeBits & QS_POSTMESSAGE ) printf("QS_POSTMESSAGE "); if ( queue->WakeBits & QS_TIMER ) printf("QS_TIMER "); if ( queue->WakeBits & QS_PAINT ) printf("QS_PAINT "); printf("\n"); for ( i=0; i < maxMessages; i++ ) { printf( "HWnd: %04X Msg: %04X WParam: %04X LParam: %08lX\n", queuemsg->hwnd, queuemsg->message, queuemsg->wParam, queuemsg->lParam ); queuemsg++; } printf("\n"); } // // Get a pointer to the application message queue. Then, puts // some messages into the queue, and retrieve them. We display // the contents of the queue at each state, so that we can see // the principles involved. // void ExamineQueue(void) { QUEUE far *queue; MSG msg; queue = MK_FP( GetTaskQueue(GetCurrentTask()), 0 ); if ( !queue ) { printf("Unable to find message queue\n"); return; } printf("Here we have an empty queue:\n\n"); DumpQueueContents(queue); printf( "We'll now call PostAppMessage() to put some messages in\n" "the queue. Note that the message count goes up, and that\n" "QS_POSTMESSAGE is now set:\n\n"); PostAppMessage(GetCurrentTask(), 0x1234, 0x5678, 0x12345678L); PostAppMessage(GetCurrentTask(), 0x2345, 0x6789, 0x12345678L); PostAppMessage(GetCurrentTask(), 0x3456, 0x789A, 0x12345678L); PostAppMessage(GetCurrentTask(), 0x4567, 0x89AB, 0x12345678L); DumpQueueContents(queue); printf( "We'll now call GetMessage() to remove a message. The\n" "message still appears in the message array, but the Read\n" "pointer has been incremented. We also print out the\n" "contents of the retrieved message to show that it matches\n" "what was in the queue:\n\n"); GetMessage(&msg, 0, 0, 0); DumpQueueContents(queue); printf( "The message retrieved into the MSG struct:\n" "HWnd: %04X Msg: %04X WParam: %04X LParam: %08lX\n\n", msg.hwnd, msg.message, msg.wParam, msg.lParam ); printf( "We now call GetMessage 3 more times to get rid of the\n" "remaining messages. Note that the Read and Write ptrs are\n" "equal, the QS_POSTMESSAGE flag is no longer set, and the\n" "message count field shows 0. Thus, the queue is considered\n" "to be empty:\n\n"); GetMessage(&msg, 0, 0, 0); GetMessage(&msg, 0, 0, 0); GetMessage(&msg, 0, 0, 0); DumpQueueContents(queue); } int main() { // This program uses the message queue format for Windows // 3.1. Abort if running under any other version. if ( LOWORD(GetVersion()) != 0x0A03 ) { winio_warn(FALSE, "QUEUE", "This program requires Windows 3.1"); return 1; } // Turn off repaints. If we don't do this, the WINIO library // will attempt to use the queue while we're in the process of // examining it. winio_setbusy(); winio_setpaint(winio_current(), FALSE); ExamineQueue(); // Turn the repaints back on. This allows WINIO to refresh // the display with all the output that was created in // ExamineQueue(). winio_setpaint(winio_current(), TRUE); winio_resetbusy(); winio_home(winio_current()); return 0; }