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