|
|
1.1 root 1: #include <windows.h>
2: #include <string.h>
3: #include <malloc.h>
4: #include "console.h"
5:
1.1.1.2 ! root 6: /* Microsoft Developer Support
! 7: Copyright (c) 1992 Microsoft Corporation */
! 8:
1.1 root 9: /********************************************************************
10: * FUNCTION: invertRectangle(HANDLE hConOut, COORD coordStart, *
11: * COORD coordCur) *
12: * *
13: * PURPOSE: invert the attributes of the rectangle defined as the *
14: * area between two input COORD parameters *
15: * *
16: * INPUT: the output handle of the console to make the changes to, *
17: * and two sets of COORD structures defining the rectangle to *
18: * invert *
19: ********************************************************************/
20:
21: void invertRectangle(HANDLE hConOut, COORD coordStart, COORD coordCur)
22: {
23: WORD *awLineAttr;
24: unsigned i;
25: DWORD dwBoxWidth;
26: WORD top, left, right, bottom;
27: BOOL bSuccess;
28: DWORD dwNumAttrsRead;
29:
30: /* convert coordSart to upper left & coordCur to lower right */
31: top = min(coordStart.Y, coordCur.Y);
32: bottom = max(coordStart.Y, coordCur.Y);
33: left = min(coordStart.X, coordCur.X);
34: right = max(coordStart.X, coordCur.X);
35: coordStart.X = left;
36: coordStart.Y = top;
37: coordCur.X = right;
38: coordCur.Y = bottom;
39: /* get the width of the selected area */
40: dwBoxWidth = right - left + 1;
41: /* allocate a buffer for the attributes read from the console */
42: awLineAttr = (PWORD) malloc(getConX(hConOut));
43: PERR(awLineAttr, "malloc");
44: /* for each line in the selected area */
45: while (coordStart.Y <= coordCur.Y)
46: {
47: /* read the attributes on that line */
48: bSuccess = ReadConsoleOutputAttribute(hConOut, awLineAttr,
49: dwBoxWidth, coordStart, &dwNumAttrsRead);
50: PERR(bSuccess, "ReadConsoleOutputAttribute");
51: /* for each attribute in the line, invert the color */
52: for (i = 0; i < dwBoxWidth; i++)
53: awLineAttr[i] = ~awLineAttr[i];
54: /* put the inverted color back on the line */
55: bSuccess = WriteConsoleOutputAttribute(hConOut, awLineAttr, dwBoxWidth,
56: coordStart, &dwNumAttrsRead);
57: PERR(bSuccess, "WriteConsoleOutputAttribute");
58: coordStart.Y++; /* go to the next line */
59: }
60: free(awLineAttr); /* free allocated attribute buffer */
61: return;
62: }
63:
64:
65: /********************************************************************
66: * FUNCTION: demoReadConOut(HANDLE hConOut) *
67: * *
68: * PURPOSE: demonstrate ReadConsoleOutput, WriteConsoleOutput, *
69: * ReadConsoleOutputAttribute, and *
70: * WriteConsoleOutputAttribute. Implement a cut and past *
71: * function; as the user clicks and drags the mouse, invert *
72: * the selection rectangle to show the area selected. When *
73: * the mouse button is released, copy the selected area and *
74: * paste it to the console *
75: * *
76: * INPUT: the output handle to read from and write to *
77: ********************************************************************/
78:
79: void demoReadConOut(HANDLE hConOut)
80: {
81: BOOL bSuccess;
82: INPUT_RECORD inputBuffer;
83: DWORD dwStdInMode;
84: HANDLE hStdIn;
85: DWORD dwInputEvents;
86: COORD coordStart, coordEnd, coordDest = {0, 0};
87: BOOL bDragMode = FALSE; /* mode flag - selecting (dragging) or not? */
88: COORD coordPrev; /* coordinates of the start of the selected area */
89: CHAR_INFO *pCharInfo; /* buffer to store info from ReadConsoleOutput */
90: COORD coordBufSize; /* the size of the buffer to read into */
91: SMALL_RECT srReadRegion; /* source rectangle to read from */
92: WORD top, left, right, bottom; /* sides of the source rectangle */
93: CONSOLE_SCREEN_BUFFER_INFO csbi; /* used to get cursor position */
94:
95: setConTitle(__FILE__);
96: myPuts(hConOut, "Let's implement a simple cut & paste with the left mouse\n"
97: "button. Click and drag to select an area of the screen\n"
98: "to copy. We will read, invert, then write the screen attributes\n"
99: "of the area you are dragging over to show the current\n"
100: "selection. Release the mouse button and I will read the\n"
101: "screen contained in the output area and print the contents\n"
102: "of the buffer to the screen at the current cursor location.\n"
103: "Hit ESC to return.\n\n");
104: hStdIn = GetStdHandle(STD_INPUT_HANDLE);
1.1.1.2 ! root 105: PERR(hStdIn != INVALID_HANDLE_VALUE, "GetStdHandle");
1.1 root 106: /* save the console mode */
107: bSuccess = GetConsoleMode(hStdIn, &dwStdInMode);
108: PERR(bSuccess, "GetConsoleMode");
109: /* enable mouse input */
110: bSuccess = SetConsoleMode(hStdIn, dwStdInMode | ENABLE_MOUSE_INPUT);
111: PERR(bSuccess, "SetConsoleMode");
112: for(;;)
113: {
114: /* get an input event */
115: bSuccess = ReadConsoleInput(hStdIn, &inputBuffer, 1, &dwInputEvents);
116: PERR(bSuccess, "ReadConsoleInput");
117: switch (inputBuffer.EventType)
118: {
119: case KEY_EVENT:
120: /* is it an ESC character? */
121: if (inputBuffer.Event.KeyEvent.bKeyDown &&
122: inputBuffer.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
123: {
124: /* set input mode back to what it was originally and return */
125: bSuccess = SetConsoleMode(hStdIn, dwStdInMode);
126: PERR(bSuccess, "SetConsoleMode");
127: return;
128: }
129: break;
130: case MOUSE_EVENT:
131: /* was this was a click event? */
132: if (inputBuffer.Event.MouseEvent.dwEventFlags != MOUSE_MOVED)
133: /* is only leftmost button down? */
134: {
135: if(inputBuffer.Event.MouseEvent.dwButtonState ==
136: FROM_LEFT_1ST_BUTTON_PRESSED)
137: {
138: /* save the starting coordinates of the selected area */
139: coordStart = coordPrev =
140: inputBuffer.Event.MouseEvent.dwMousePosition;
141: /* invert the single char attribute the cursor is on */
142: invertRectangle(hConOut, coordStart, coordStart);
143: bDragMode = TRUE; /* we are now in 'drag' mode */
144: }
145: else /* button #1 has just been released */
146: {
147: /* if we're not in drag mode, break; we might get a mouse */
148: /* button release when gaining the focus */
149: if (!bDragMode)
150: break;
151: /* save the coordinates of the mouse release */
152: coordEnd = inputBuffer.Event.MouseEvent.dwMousePosition;
153: bDragMode = FALSE; /* we're not in 'drag' mode anymore */
154: /* invert the rectangle back to normal */
155: invertRectangle(hConOut, coordStart, coordEnd);
156: /* copy the buffer in the rectangle and output it. First convert */
157: /* coordSart to upper left & coordCur to lower right */
158: top = min(coordStart.Y, coordEnd.Y);
159: left = min(coordStart.X, coordEnd.X);
160: bottom = max(coordStart.Y, coordEnd.Y);
161: right = max(coordStart.X, coordEnd.X);
162: coordStart.X = srReadRegion.Left = left;
163: coordStart.Y = srReadRegion.Top = top;
164: coordEnd.X = srReadRegion.Right = right;
165: coordEnd.Y = srReadRegion.Bottom = bottom;
166: /* get the size of the selected rectangle */
167: coordBufSize.X = coordEnd.X - coordStart.X + (SHORT) 1;
168: coordBufSize.Y = coordEnd.Y - coordStart.Y + (SHORT) 1;
169: /* allocate a buffer for the screen rectangle */
170: pCharInfo = malloc(coordBufSize.X * coordBufSize.Y *
171: sizeof(CHAR_INFO));
172: PERR(pCharInfo, "malloc");
173: /* read the screen rectangle into the buffer */
174: bSuccess = ReadConsoleOutput(hConOut, /* output buffer */
175: pCharInfo, /* buffer that receives data */
176: coordBufSize, /* col/row size of destination buffer */
177: coordDest, /* upper-left cell to write data to in dest */
178: &srReadRegion); /* screen buffer rectangle to read from */
179: PERR(bSuccess, "ReadConsoleOutput");
180: /* get current cursor position */
181: bSuccess = GetConsoleScreenBufferInfo(hConOut, &csbi);
182: PERR(bSuccess, "GetConsoleScreenBufferInfo");
183: /* set up an output destination rectangle for the buffer. */
184: /* Put it just below the current cursor position. */
185: srReadRegion.Top = csbi.dwCursorPosition.Y;
186: srReadRegion.Bottom = csbi.dwCursorPosition.Y + (bottom - top);
187: srReadRegion.Left = 0;
188: srReadRegion.Right = right - left;
189: bSuccess = WriteConsoleOutput(hConOut, /* output buffer */
190: pCharInfo, /* buffer with data to write */
191: coordBufSize, /* col/row size of source buffer */
192: coordDest, /* upper-left cell to write data from in src */
193: &srReadRegion); /* screen buffer rect to write data to */
194: PERR(bSuccess, "WriteConsoleOutput");
195: free(pCharInfo);
196: }
197: }
198: /* is it a mouse movement while we are in drag mode? */
199: if (inputBuffer.Event.MouseEvent.dwEventFlags == MOUSE_MOVED &&
200: bDragMode)
201: {
202: /* if the cursor moves from the rectangle it was previously in, */
203: /* invert the old rectangle then invert the new rectangle. */
204: /* Compare the current coordinates with the previous coordinates */
205: if (memcmp(&inputBuffer.Event.MouseEvent.dwMousePosition,
206: &coordPrev, sizeof(COORD)))
207: {
208: /* You could be clever and only invert what needs to be */
209: /* inverted rather than the entire two rectangles... */
210: /* Invert the old rectangle */
211: invertRectangle(hConOut, coordStart, coordPrev);
212: /* and invert the new rectangle */
213: invertRectangle(hConOut, coordStart,
214: inputBuffer.Event.MouseEvent.dwMousePosition);
215: /* save the current mouse position to the previous position */
216: memcpy(&coordPrev,
217: &inputBuffer.Event.MouseEvent.dwMousePosition,
218: sizeof(COORD));
219: }
220: }
221: break;
222: } /* switch */
223: } /* while */
224: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.