|
|
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.