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