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