|
|
1.1 root 1: #include <windows.h>
2: #include <stdio.h>
3: #include <string.h>
4: #include <stdlib.h>
5: #include "console.h"
6:
1.1.1.2 ! root 7: /* Microsoft Developer Support
! 8: Copyright (c) 1992 Microsoft Corporation */
! 9:
1.1 root 10: /* used to set our initial console screen buffer size */
11: #define CONX 80
12: #define CONY 43
13:
14: /* prototypes of externally defined demo functions */
15: extern void demoAllocFree(HANDLE hConOld, HANDLE *hConsole);
16: extern void demoCreate(HANDLE hConOld);
17: extern void demoFillAtt(HANDLE hConOut);
18: extern void demoFillChar(HANDLE hConOut);
19: extern void demoFlush(HANDLE hConOut);
20: extern void demoCursor(HANDLE hConOut);
21: extern void demoConMode(HANDLE hConOut);
22: extern void demoConInfo(HANDLE hConOut);
23: extern void demoGetTitle(HANDLE hConOut);
24: extern void demoGetLargest(HANDLE hConOut);
25: extern void demoGetNumEvents(HANDLE hConOut);
26: extern void demoGetNumBut(HANDLE hConOut);
27: extern void demoReadConOut(HANDLE hConOut);
28: extern void demoReadConChar(HANDLE hConOut);
29: extern void demoScrollCon(HANDLE hConOut);
30: extern void demoSizeInfo(HANDLE hConOut);
31: extern void demoSetCtrlHandler(HANDLE hConOut);
32: extern void demoWriteIn(HANDLE hConOut);
33:
34: /* information to display on the screen for user to click on */
35: PCHAR conAPIs[] = {
36: "AllocConsole Creates a console for the current process",
37: "CreateConsoleScreenBuffer Returns a handle to a new screen buffer",
38: "FillConsoleOutputAttribute Writes attributes to the screen buffer",
39: "FillConsoleOutputCharacter Writes characters to the screen buffer",
40: "FlushConsoleInputBuffer Clears the console input buffer",
41: "FreeConsole Frees the current console",
42: "GetConsoleCursorInfo Returns console size and visibility",
43: "GetConsoleMode Returns console input or output mode",
44: "GetConsoleScreenBufferInfo Returns screen-buffer information",
45: "GetConsoleTitle Returns console-window title",
46: "GetLargestConsoleWindowSize Returns largest possible window size",
47: "GetNumberOfConsoleInputEvents Retrieves number of console-queue events",
48: "GetNumberOfConsoleMouseButtons Retrieves number of mouse buttons",
49: "PeekConsoleInput Previews console input data",
50: "ReadConsoleInput Reads console input data",
51: "ReadConsoleOutput Reads screen-buffer data",
52: "ReadConsoleOutputAttribute Reads a console attribute string",
53: "ReadConsoleOutputCharacter Reads a screen-buffer string",
54: "ScrollConsoleScreenBuffer Scrolls data in the screen buffer",
55: "SetConsoleActiveScreenBuffer Changes displayed screen buffer",
56: "SetConsoleCursorInfo Sets cursor size and visibility",
57: "SetConsoleCursorPosition Sets cursor position",
58: "SetConsoleMode Sets console input or output mode",
59: "SetConsoleScreenBufferSize Changes screen-buffer size",
60: "SetConsoleTextAttribute Sets attributes for screen text",
61: "SetConsoleTitle Sets console-window title string",
62: "SetConsoleWindowInfo Sets console window size",
63: "SetConsoleCtrlHandler Sets console ctrl-c handler",
64: "WriteConsoleInput Writes to console input buffer",
65: "WriteConsoleOutput Writes to screen buffer",
66: "WriteConsoleOutputAttribute Writes an attribute string to console",
67: "WriteConsoleOutputCharacter Writes a character string to console"
68: };
69:
70: /* this variable holds the number next to the API on the screen that */
71: /* the user clicks on */
72: enum cAPIs { ALLOC = 1, CREATE, FILLATT, FILLCHAR, FLUSH, FREE, GETCUR,
73: GETMODE, GETCONINFO, GETTITLE, GETLARGEST, GETNUMEV, GETNUMBUT, PEEK,
74: READCONIN, READCONOUT, READCONATT, READCONCHAR, SCROLL, SETACTIVE,
75: SETCURINF, SETCURPOS, SETMODE, SETSIZE, SETATT, SETTITLE, SETINFO,
76: SETHAND, WRITEIN, WRITEOUT, WRITEATT, WRITECHAR };
77:
78:
79: /*****************************************************************
80: * FUNCTION: myGetchar(void) *
81: * *
82: * PURPOSE: get a single character from the standard input handle *
83: * *
84: * INPUT: none *
85: * *
86: * RETURNS: the char received from the console *
87: *****************************************************************/
88:
89: CHAR myGetchar(void)
90: {
91: HANDLE hStdIn; /* standard input */
92: DWORD dwInputMode; /* to save the input mode */
93: BOOL bSuccess;
94: CHAR chBuf; /* buffer to read into */
95: DWORD dwRead;
96:
97: /* get the standard input handle to read from. There is only one */
98: /* instance of standard input per process at any given time */
99: hStdIn = GetStdHandle(STD_INPUT_HANDLE);
1.1.1.2 ! root 100: PERR(hStdIn != INVALID_HANDLE_VALUE, "GetStdHandle");
1.1 root 101: /* save the console mode */
102: bSuccess = GetConsoleMode(hStdIn, &dwInputMode);
103: PERR(bSuccess, "GetconsoleMode");
104: /* disable line input. Echo input must be disabled when disabling */
105: /* line input */
106: bSuccess = SetConsoleMode(hStdIn, dwInputMode & ~ENABLE_LINE_INPUT &
107: ~ENABLE_ECHO_INPUT);
108: PERR(bSuccess, "SetConsoleMode");
109: /* read a character from the console input */
110: bSuccess = ReadFile(hStdIn, &chBuf, sizeof(chBuf), &dwRead, NULL);
111: PERR(bSuccess, "ReadFile");
112: /* restore the original console input mode */
113: bSuccess = SetConsoleMode(hStdIn, dwInputMode);
114: PERR(bSuccess, "SetConsoleMode");
115: return(chBuf);
116: }
117:
118:
119: /********************************************************************
120: * FUNCTION: perrError(void) *
121: * *
122: * PURPOSE: beep twice and abort program *
123: * *
124: * INPUT: none *
125: * *
126: * RETURNS: none *
127: * *
128: * COMMENTS: only called from perr() when a fatal error has occurred *
129: ********************************************************************/
130:
131: void perrError(void)
132: {
133: DWORD dwLastError; /* for debugger purposes */
134:
135: dwLastError = GetLastError();
136: /* we can't output an error message - beep instead */
137: Beep(600, 500);
138: Beep(700, 500);
139: exit(1);
140: }
141:
142:
143: /*********************************************************************
144: * FUNCTION: perr(PCHAR szFileName, int line, PCHAR szApiName, *
145: * DWORD dwError) *
146: * *
147: * PURPOSE: report API errors. Allocate a new console buffer, display *
148: * error number and error text, restore previous console *
149: * buffer *
150: * *
151: * INPUT: current source file name, current line number, name of the *
152: * API that failed, and the error number *
153: * *
154: * RETURNS: none *
155: *********************************************************************/
156:
157: /* this is the size of the buffer for the error message text */
158: #define MSG_BUF_SIZE 512
159:
160: void perr(PCHAR szFileName, int line, PCHAR szApiName, DWORD dwError)
161: {
162: BOOL bSuccess;
163: HANDLE hConTemp; /* temp console buffer to put error message on */
164: HANDLE hCurrentCon; /* to save the current console so we can restore it */
165: CHAR szTemp[256];
166: DWORD cCharsWritten;
167: DWORD dwLastError; /* for debugging purposes */
168: CHAR msgBuf[MSG_BUF_SIZE]; /* buffer for message text from system */
169:
170: /* create a handle to the current console buffer */
171: hCurrentCon = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_READ |
172: FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1.1.1.2 ! root 173: if (hCurrentCon == INVALID_HANDLE_VALUE)
1.1 root 174: {
175: dwLastError = GetLastError();
176: /* just in case this works */
177: printf("Fatal error in perr() on line %d: %d\n", __LINE__, dwLastError);
178: Beep(600, 500);
179: exit(1);
180: }
181: /* create a temporary console buffer that we can write on */
182: hConTemp = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
183: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER,
184: NULL);
1.1.1.2 ! root 185: if (hConTemp == INVALID_HANDLE_VALUE)
1.1 root 186: {
187: dwLastError = GetLastError();
188: printf("Fatal error in perr() on line %d: %d\n", __LINE__, dwLastError);
189: Beep(600, 500);
190: exit(1);
191: }
192: /* make the temp buffer to the current buffer */
193: bSuccess = SetConsoleActiveScreenBuffer(hConTemp);
194: if (!bSuccess)
195: {
196: dwLastError = GetLastError();
197: printf("Fatal error in perr() on line %d: %d\n", __LINE__, dwLastError);
198: Beep(600, 500);
199: exit(1);
200: }
201: /* set red on white text for future text output */
202: SetConsoleTextAttribute(hConTemp, FOREGROUND_RED | BACKGROUND_WHITE);
203: /* format our error message */
204: sprintf(szTemp, "%s: Error %d from %s on line %d\n", szFileName,
205: dwError, szApiName, line);
206: /* write the message to the console */
207: bSuccess = WriteFile(hConTemp, szTemp, strlen(szTemp), &cCharsWritten,
208: NULL);
209: if (!bSuccess)
210: perrError();
211: memset(msgBuf, 0, sizeof(msgBuf));
212: /* get the text description for that error number from the system */
213: cCharsWritten = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
214: getConX(hConTemp), NULL, dwError, MAKELANGID(0, SUBLANG_ENGLISH_US),
215: msgBuf, sizeof(msgBuf), NULL);
216: if (!cCharsWritten)
217: perrError();
218: else
219: {
220: /* write the text description to the console */
221: bSuccess = WriteFile(hConTemp, msgBuf, strlen(msgBuf), &cCharsWritten,
222: NULL);
223: if (!bSuccess)
224: perrError();
225: }
226: myGetchar();
227: /* reset the current buffer to the original one */
228: bSuccess = SetConsoleActiveScreenBuffer(hCurrentCon);
229: if (!bSuccess)
230: perrError();
231: CloseHandle(hConTemp);
232: bSuccess = CloseHandle(hCurrentCon);
233: if (!bSuccess)
234: perrError();
235: return;
236: }
237:
238: /*************************************************************************
239: * FUNCTION: myPuts(HANDLE hConsole, PCHAR s) *
240: * *
241: * PURPOSE: write a string to the given console buffer, appending a cr/lf *
242: * *
243: * INPUT: the console to write to, and the string to write *
244: * *
245: * RETURNS: TRUE if success, FALSE if an error occured *
246: *************************************************************************/
247:
248: BOOL myPuts(HANDLE hConsole, PCHAR s)
249: {
250: BOOL bSuccess;
251: DWORD cCharsWritten;
252: const PCHAR crlf = "\n";
253: BOOL retflag = TRUE;
254:
255: /* write the string to the console */
256: bSuccess = WriteFile(hConsole, s, strlen(s), &cCharsWritten, NULL);
257: PERR(bSuccess, "WriteFile");
258: retflag = bSuccess;
259: /* put a carriage return & line feed after the string */
260: bSuccess = WriteFile(hConsole, crlf, strlen(crlf), &cCharsWritten, NULL);
261: PERR(bSuccess, "WriteFile");
262: if (!bSuccess)
263: retflag = FALSE;
264: return(retflag);
265: }
266:
267:
268: /********************************************************************
269: * FUNCTION: getConX(HANDLE hCon) *
270: * *
271: * PURPROSE: to get the current width of the console output buffer *
272: * *
273: * INPUT: the handle to get the information for *
274: * *
275: * RETURNS: the width of the current console output buffer, in chars *
276: ********************************************************************/
277:
278: SHORT getConX(HANDLE hCon)
279: {
280: CONSOLE_SCREEN_BUFFER_INFO csbi;
281: BOOL bSuccess;
282:
283: bSuccess = GetConsoleScreenBufferInfo(hCon, &csbi);
284: PERR(bSuccess, "GetConsoleScreenBufferInfo");
285: return(csbi.dwSize.X);
286: }
287:
288:
289: /*********************************************************************
290: * FUNCTION: getConY(HANDLE hCon) *
291: * *
292: * PURPROSE: to get the current height of the console output buffer *
293: * *
294: * INPUT: the handle to get the information for *
295: * *
296: * RETURNS: the height of the current console output buffer, in chars *
297: *********************************************************************/
298:
299:
300: SHORT getConY(HANDLE hCon)
301: {
302: CONSOLE_SCREEN_BUFFER_INFO csbi;
303: BOOL bSuccess;
304:
305: bSuccess = GetConsoleScreenBufferInfo(hCon, &csbi);
306: PERR(bSuccess, "GetConsoleScreenBufferInfo");
307: return(csbi.dwSize.Y);
308: }
309:
310:
311: /*************************************************************************
312: * FUNCTION: showConAPIs(HANDLE hConsole) *
313: * *
314: * PURPOSE: to display a list of console APIs on the given console buffer *
315: * *
316: * INPUT: the console to display the APIs on *
317: * *
318: * RETURNS: none *
319: *************************************************************************/
320:
321: void showConAPIs(HANDLE hConsole)
322: {
323: COORD coordScreen = {CONX, CONY}; /* used to set the console buffer size */
324: /* used to set the console window size */
325: SMALL_RECT srWindowRect = {0, 0, CONX - 1, CONY - 1};
326: int i;
327: BOOL bSuccess;
328: DWORD cCharsWritten;
329: CHAR szTemps[128];
330: WORD wConBufSize; /* used to hold current console buffer size */
331:
332: /* get the current console buffer size, in chars */
333: wConBufSize = getConX(hConsole) * getConY(hConsole);
334: /* force an CONX x CONY screen */
335: /* if the current buffer is larger than what we want, resize the */
336: /* console window first, then the buffer */
337: if (wConBufSize > CONX * CONY)
338: {
339: bSuccess = SetConsoleWindowInfo(hConsole, TRUE, &srWindowRect);
340: PERR(bSuccess, "SetConsoleWindowInfo");
341: bSuccess = SetConsoleScreenBufferSize(hConsole, coordScreen);
342: PERR(bSuccess, "SetConsoleScreenBufferSize");
343: }
344: /* if the current buffer is smaller than what we want, resize the */
345: /* buffer first, then the console window */
346: if (wConBufSize < CONX * CONY)
347: {
348: bSuccess = SetConsoleScreenBufferSize(hConsole, coordScreen);
349: PERR(bSuccess, "SetConsoleScreenBufferSize");
350: bSuccess = SetConsoleWindowInfo(hConsole, TRUE, &srWindowRect);
351: PERR(bSuccess, "SetConsoleWindowInfo");
352: }
353: coordScreen.X = 0;
354: coordScreen.Y = 0;
355: /* set the screen */
356: bSuccess = FillConsoleOutputAttribute(hConsole, BACKGROUND_BLUE,
357: CONX * CONY, coordScreen, &cCharsWritten);
358: PERR(bSuccess, "FillConsoleOutputAttribute");
359: /* set attributes for new writes to the console */
360: bSuccess = SetConsoleTextAttribute(hConsole, BACKGROUND_BLUE |
361: FOREGROUND_WHITE);
362: PERR(bSuccess, "SetConsoleTextAttribute");
363: /* fill screen with API list */
364: for (i = 0; i < sizeof(conAPIs) / sizeof(conAPIs[0]); i++)
365: {
366: coordScreen.X = 0;
367: coordScreen.Y = (SHORT) (i + 2); /* start on third line (zero based) */
368: /* position the cursor to start the API list */
369: bSuccess = SetConsoleCursorPosition(hConsole, coordScreen);
370: PERR(bSuccess, "SetConsoleCursorPosition");
371: /* format a line and write it to the screen */
372: sprintf(szTemps, "%-3d%s", i + 1, conAPIs[i]);
373: myPuts(hConsole, szTemps);
374: /* color the number yellow on blue */
375: bSuccess = FillConsoleOutputAttribute(hConsole, FOREGROUND_YELLOW |
376: FOREGROUND_INTENSITY | BACKGROUND_BLUE, 3, coordScreen,
377: &cCharsWritten);
378: PERR(bSuccess, "FillConsoleOutputAttribute");
379: coordScreen.X = 3;
380: /* color text light cyan on blue */
381: bSuccess = FillConsoleOutputAttribute(hConsole, FOREGROUND_CYAN |
382: FOREGROUND_INTENSITY | BACKGROUND_BLUE, strlen(conAPIs[i]),
383: coordScreen, &cCharsWritten);
384: PERR(bSuccess, "FillConsoleOutputAttribute");
385: }
386: myPuts(hConsole, "\nClick on an API to see a demonstration of that API.\n"
387: "Hit ESC to exit the program.\n");
388: return;
389: }
390:
391:
392: /*************************************************************************
393: * FUNCTION: putStatusLine(HANDLE hOut, PCHAR buf) *
394: * *
395: * PURPOSE: display a string on the top line of the console output buffer *
396: * *
397: * INPUT: the output handle, the string to display *
398: * *
399: * RETURNS: none *
400: *************************************************************************/
401:
402: void putStatusLine(HANDLE hOut, PCHAR buf)
403: {
404: BOOL bSuccess;
405: /* position the status line at (0, 0) */
406: const COORD dwWriteCoord = {0, 0};
407: DWORD cCharsWritten;
408: int len; /* the length of the input string parameter */
409: CHAR szTemp[256];
410: SHORT sWidth; /* console width */
411:
412: sWidth = getConX(hOut);
413: strcpy(szTemp, buf);
414: len = strlen(szTemp);
415: memset(szTemp + len, ' ', sWidth - len); /* blank out rest of line */
416: /* write the string to the console at the correct position */
417: bSuccess = WriteConsoleOutputCharacter(hOut, szTemp, sWidth,
418: dwWriteCoord, &cCharsWritten);
419: PERR(bSuccess, "WriteConsoleOutput");
420: /* color the status line so it stands out */
421: bSuccess = FillConsoleOutputAttribute(hOut, FOREGROUND_RED |
422: BACKGROUND_WHITE, sWidth, dwWriteCoord, &cCharsWritten);
423: PERR(bSuccess, "FillConsoleOutputAttribute");
424: return;
425: }
426:
427:
428: /********************************************************************
429: * FUNCTION: demoAPI(HANDLE *hConsole, enum cAPIs apiNumber) *
430: * *
431: * PURPOSE: call the correct demo function based on the input index *
432: * *
433: * INPUT: current console output buffer, and screen index of the API *
434: * to demonstrate *
435: * *
436: * RETURNS: none *
437: ********************************************************************/
438:
439: static void demoAPI(HANDLE *phConsole, enum cAPIs apiNumber)
440: {
441: const COORD coordScreen = {0, 0};
442: DWORD cCharsWritten;
443: BOOL bSuccess;
444: HANDLE hConTemp;
445: CHAR szConsoleTitle[128]; /* to store the console title */
446: DWORD dwCharsRead;
447:
448: /* create a temp screen buffer to write to */
449: hConTemp = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
450: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER,
451: NULL);
1.1.1.2 ! root 452: PERR(hConTemp != INVALID_HANDLE_VALUE,
! 453: "CreateConsoleScreenBuffer");
1.1 root 454: /* make it the active buffer */
455: bSuccess = SetConsoleActiveScreenBuffer(hConTemp);
456: PERR(bSuccess, "SetConsoleActiveScreenBuffer");
457: /* clear screen & save the console title */
458: cls(hConTemp);
459: bSuccess = FillConsoleOutputAttribute(hConTemp, BACKGROUND_CYAN,
460: getConX(hConTemp) * getConY(hConTemp), coordScreen, &cCharsWritten);
461: PERR(bSuccess, "FillConsoleOutputAttribute");
462: bSuccess = SetConsoleTextAttribute(hConTemp, BACKGROUND_CYAN);
463: PERR(bSuccess, "SetConsoleTextAttribute");
464: dwCharsRead = GetConsoleTitle(szConsoleTitle, sizeof(szConsoleTitle));
465: PERR(dwCharsRead, "GetConsoleTitle");
466:
467: /* flush the input buffer and call the correct demo function */
468: bSuccess = FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
469: PERR(bSuccess, "FlushConsoleInputBuffer");
470: switch(apiNumber)
471: {
472: case ALLOC:
473: case FREE:
474: demoAllocFree(hConTemp, phConsole);
475: return;
476: break;
477: case CREATE:
478: case SETACTIVE:
479: case SETATT:
480: demoCreate(hConTemp);
481: break;
482: case FILLATT:
483: case WRITECHAR:
484: demoFillAtt(hConTemp);
485: break;
486: case FILLCHAR:
487: demoFillChar(hConTemp);
488: break;
489: case FLUSH:
490: demoFlush(hConTemp);
491: break;
492: case GETCUR:
493: case SETCURINF:
494: case SETCURPOS:
495: demoCursor(hConTemp);
496: break;
497: case GETMODE:
498: case SETMODE:
499: demoConMode(hConTemp);
500: break;
501: case GETCONINFO:
502: demoConInfo(hConTemp);
503: break;
504: case GETTITLE:
505: case SETTITLE:
506: demoGetTitle(hConTemp);
507: break;
508: case GETLARGEST:
509: demoGetLargest(hConTemp);
510: break;
511: case GETNUMEV:
512: case PEEK:
513: case READCONIN:
514: demoGetNumEvents(hConTemp);
515: break;
516: case GETNUMBUT:
517: demoGetNumBut(hConTemp);
518: break;
519: case READCONOUT:
520: case WRITEOUT:
521: case READCONATT:
522: case WRITEATT:
523: demoReadConOut(hConTemp);
524: break;
525: case READCONCHAR:
526: demoReadConChar(hConTemp);
527: break;
528: case SCROLL:
529: demoScrollCon(hConTemp);
530: break;
531: case SETSIZE:
532: case SETINFO:
533: demoSizeInfo(hConTemp);
534: break;
535: case SETHAND:
536: demoSetCtrlHandler(hConTemp);
537: break;
538: case WRITEIN:
539: demoWriteIn(hConTemp);
540: break;
541: default:
542: break;
543: }
544: CloseHandle(hConTemp); /* free temporary console buffer */
545: /* reset active buffer to original buffer. If the temp buffer has been */
546: /* resized, the console window will automatically be sized correctly */
547: /* when the current console is set back to the old one */
548: bSuccess = SetConsoleActiveScreenBuffer(*phConsole);
549: PERR(bSuccess, "SetConsoleActiveScreenBuffer");
550: /* restore the original console title */
551: bSuccess = SetConsoleTitle(szConsoleTitle);
552: PERR(bSuccess, "SetConsoleTitle");
553: /* flush the input buffer to remove any 'leftover' clicks or key events */
554: bSuccess = FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
555: PERR(bSuccess, "FlushConsoleInputBuffer");
556: return;
557: }
558:
559:
560: /************************************************************************
561: * FUNCTION: cls(HANDLE hConsole) *
562: * *
563: * PURPOSE: clear the screen by filling it with blanks, then home cursor *
564: * *
565: * INPUT: the console buffer to clear *
566: * *
567: * RETURNS: none *
568: *************************************************************************/
569:
570: void cls(HANDLE hConsole)
571: {
572: COORD coordScreen = { 0, 0 }; /* here's where we'll home the cursor */
573: BOOL bSuccess;
574: DWORD cCharsWritten;
575:
576: /* fill the entire screen with blanks */
577: bSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR) ' ',
578: getConX(hConsole) * getConY(hConsole), coordScreen, &cCharsWritten);
579: PERR(bSuccess, "FillConsoleOutputCharacter");
580: /* put the cursor at (0, 0) */
581: bSuccess = SetConsoleCursorPosition(hConsole, coordScreen);
582: PERR(bSuccess, "SetConsoleCursorPosition");
583: return;
584: }
585:
586:
587: /*********************************************************************
588: * FUNCTION: setConTitle *
589: * *
590: * PURPOSE: simply set the current console title. Called by each demo *
591: * function to specify the name of the source file that *
592: * contains the demo function. *
593: * *
594: * INPUT: null terminated string *
595: *********************************************************************/
596:
597: void setConTitle(PCHAR szTitle)
598: {
599: BOOL bSuccess;
600:
601: /* set the console title to the input string parameter */
602: bSuccess = SetConsoleTitle(szTitle);
603: PERR(bSuccess, "SetConsoleTitle");
604: return;
605: }
606:
607:
608: /*********************************************************************
609: * FUNCTION: main *
610: * *
611: * PURPOSE: main input loop. Set up console input and output *
612: * attributes, then read the input queue and process input *
613: * events. If ESC is hit, end the process. If the mouse is *
614: * clicked, read the line from the output console where the *
615: * mouse was clicked. If an index number can be found at the *
616: * beginning of the line, call the appropriate demo function *
617: * to demonstrate that API. All input event information is *
618: * displayed on the status line on the top line. *
619: * *
620: * INPUT: none *
621: * *
622: * RETURNS: 1 if can't free console, 2 if can't allocate a console, 0 *
623: * for a normal exit *
624: *********************************************************************/
625:
626: int main()
627: {
628: BOOL bSuccess;
629: HANDLE hStdIn, hStdOut; /* standard input and standard output */
630: DWORD dwMode;
631: /* array of console input event records */
632: INPUT_RECORD inputBuffer;
633: DWORD dwInputEvents; /* number of events actually read */
634: CHAR bOutBuf[256]; /* buffer to format event information into */
635: /* used to get the new console screen buffer size if it is changed */
636: COORD coordScreen; /* used when reading the index number from the screen */
637: CHAR *szLineBuf; /* buffer to read the index number into */
638: DWORD cCharsRead;
639: enum cAPIs apiNumber; /* the index number of the API read from the screen */
640: /* used when turning off the cursor */
641: CONSOLE_CURSOR_INFO cci = {100, FALSE};
642:
643: /* free the console and immediately allocate a new one. This is done so */
644: /* that when debugging under ntsd, the application output will not be */
645: /* intermingled with the debugger output. This section can be removed */
646: /* without any change in the behavior of this program */
647: bSuccess = FreeConsole();
648: /* C run-time output will not work from now on! */
649: if (!bSuccess)
650: {
651: Beep(600, 500); /* can't output an error message! */
652: return(1);
653: }
654: bSuccess = AllocConsole();
655: if (!bSuccess)
656: {
657: Beep(600, 500); /* can't output an error message! */
658: return(2);
659: }
660: /* let's put up a meaningful console title */
661: bSuccess = SetConsoleTitle("Win32 Console API Demo");
662: PERR(bSuccess, "SetConsoleTitle");
663: /* get the standard handles */
664: hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
1.1.1.2 ! root 665: PERR(hStdOut != INVALID_HANDLE_VALUE, "GetStdHandle");
1.1 root 666: hStdIn = GetStdHandle(STD_INPUT_HANDLE);
1.1.1.2 ! root 667: PERR(hStdIn != INVALID_HANDLE_VALUE, "GetStdHandle");
1.1 root 668: /* set up mouse and window input */
669: bSuccess = GetConsoleMode(hStdIn, &dwMode);
670: PERR(bSuccess, "GetConsoleMode");
671: /* when turning off ENABLE_LINE_INPUT, you MUST also turn off */
672: /* ENABLE_ECHO_INPUT. */
673: bSuccess = SetConsoleMode(hStdIn, (dwMode & ~(ENABLE_LINE_INPUT |
674: ENABLE_ECHO_INPUT)) | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
675: PERR(bSuccess, "SetConsoleMode");
676: /* hide the cursor */
677: bSuccess = SetConsoleCursorInfo(hStdOut, &cci);
678: PERR(bSuccess, "SetConsoleCursorInfo");
679: /* resize console to CONX * CONY and put list of console APIs up */
680: showConAPIs(hStdOut);
681: /* This is the main input loop. Read from the input queue and process */
682: /* the events read */
683: szLineBuf = (char *) malloc(getConX(hStdOut));
684: PERR(szLineBuf, "malloc");
685:
686: for(;;)
687: {
688: /* read an input events from the input event queue */
689: bSuccess = ReadConsoleInput(hStdIn, &inputBuffer, 1, &dwInputEvents);
690: PERR(bSuccess, "ReadConsoleInput");
691: switch (inputBuffer.EventType)
692: {
693: case KEY_EVENT:
694: if (inputBuffer.Event.KeyEvent.bKeyDown)
695: {
696: /* display the key event info on the status line */
697: sprintf(bOutBuf, "key: virtual=%d ascii=%c",
698: inputBuffer.Event.KeyEvent.wVirtualKeyCode,
699: inputBuffer.Event.KeyEvent.uChar.AsciiChar);
700: if (inputBuffer.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
701: {
702: free(szLineBuf); /* free allocated line buffer */
703: return(0);
704: }
705: putStatusLine(hStdOut, bOutBuf);
706: }
707: break;
708: case MOUSE_EVENT:
709: sprintf(bOutBuf, "mouse: %s at %d, %d",
710: (inputBuffer.Event.MouseEvent.dwEventFlags == MOUSE_MOVED ?
711: "moved" : "clicked"), inputBuffer.Event.MouseEvent.dwMousePosition.X,
712: inputBuffer.Event.MouseEvent.dwMousePosition.Y);
713: putStatusLine(hStdOut, bOutBuf);
714: /* was this a mouse click? If so dwEventFlags contains 0 */
715: /* are any mouse buttons down? If so dwButtonState is not 0 */
716: if (inputBuffer.Event.MouseEvent.dwEventFlags == 0 &&
717: inputBuffer.Event.MouseEvent.dwButtonState)
718: {
719: coordScreen.X = 0;
720: coordScreen.Y = inputBuffer.Event.MouseEvent.dwMousePosition.Y;
721: /* read the line where the mouse clicked */
722: bSuccess = ReadConsoleOutputCharacter(hStdOut, szLineBuf,
723: sizeof(szLineBuf), coordScreen, &cCharsRead);
724: PERR(bSuccess, "ReadConsoleOutputCharacter");
725: /* scan for an index number at the beginning of that line. */
726: /* if there was one read, call the correct demo function */
727: if (sscanf(szLineBuf, "%d", &apiNumber))
728: demoAPI(&hStdOut, apiNumber);
729: }
730: break;
731: case WINDOW_BUFFER_SIZE_EVENT:
732: sprintf(bOutBuf, "window: %d, %d",
733: inputBuffer.Event.WindowBufferSizeEvent.dwSize.X,
734: inputBuffer.Event.WindowBufferSizeEvent.dwSize.Y);
735: putStatusLine(hStdOut, bOutBuf);
736: Sleep(1000);
737: break;
738: } /* switch */
739: } /* while */
740: free(szLineBuf); /* free allocated line buffer */
741: return(0);
742: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.