Учитывая, что на консоли Windows 11 уже существует текст, как можно скопировать весь текст в буфер обмена с помощью C или C++?
То есть я хочу сделать программный эквивалент перетаскивания мышью по всему тексту, чтобы выделить его, а затем нажать Ctrl-C, чтобы он был захвачен в буфер обмена.
Вы задали этот вопрос вчера.
Вы можете использовать саму консоль, чтобы выделить текст мышкой и скопировать его. Моя утилита, которая копирует весь буфер консоли (включая прокручиваемую часть) в файл, использует GetConsoleScreenBufferInfo()
для создания буфера и т. д., а затем ReadConsoleOutputCharacter()
для чтения партии. Если вы хотите скопировать его в буфер обмена, вам понадобится OpenClipboard()
и т. д.
@gregspears ОП хочет «программный эквивалент» выбора и копирования. Поэтому я сомневаюсь, что они хотят, чтобы пользователь действительно вводил Ctrl-C вручную. Программа должна взять любой текст, который уже есть в консоли, и поместить его в буфер обмена.
@RemyLebeau - спасибо, в этом есть смысл. У меня есть код для этого. По вашему опытному мнению, следует ли мне опубликовать решение или этот вопрос будет закрыт сообществом? Я опубликовал множество решений за секунды и минуты до того, как сообщество закрыло вопрос ФП — похоже, что скоро появится еще один… большое спасибо за ваши рекомендации.
@gregspears Если вы думаете, что у вас есть решение, не стесняйтесь опубликовать его.
@catnip, возможно, потому, что это похоже на запрос кода.
Вот решение, как просили. Этот код я только что протестировал в MS Visual Studio и Windows OS 10.
Обратите внимание, что это непереносимый код Windows, поскольку OP запросил решение, конкретно связанное с ОС Windows, и отметил winapi
.
Эта программа выводит строку в окно консоли, затем захватывает/удаляет текст из окна экрана/консоли через Windows API ReadConsoleOutputCharacter().
Текстовые данные затем копируются в буфер обмена Windows.
#include <windows.h>
#include <stdio.h>
#include <conio.h>
/*-------------------------------------------------------------------------
copy_to_clipboard()
Adapted from https://stackoverflow.com/a/1264179/3130521
Credits: Judge Maygarden
*--------------------------------------------------------------------------*/
BOOL copy_to_clipboard(char *pBuff)
{
size_t size = strlen(pBuff)+1;
if (size > 1)
{
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, size);
memcpy(GlobalLock(hMem), pBuff, size);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
return TRUE;
}
return FALSE;
}
int main()
{
/* Get the handle to the console window*/
HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO CSBI;
int win_w,win_h,size;
char *tbuff;
DWORD num_chars_read;
COORD dwReadCoord = {0,0}; /* Read from screen top, left (0,0) */
if (hConOut == INVALID_HANDLE_VALUE)
{
printf("STDOUT not available.\n");
return 0;
}
/* Put some text to the screen */
printf("This text should match the contents of the clipboard buffer on completion.\n");
/* Get console window dims, potential text size, allocate buffer to that size */
GetConsoleScreenBufferInfo( hConOut, &CSBI );
win_w=CSBI.srWindow.Right - CSBI.srWindow.Left+1;
win_h=CSBI.srWindow.Bottom - CSBI.srWindow.Top+1;
size = win_w*win_h;
tbuff = malloc(size+1);
if (!tbuff)
{
printf("malloc() failed!\n");
return 0;
}
/* Capture the text from the console window*/
if (!ReadConsoleOutputCharacter( hConOut, tbuff, size,dwReadCoord, &num_chars_read))
{
free(tbuff);
printf("ReadConsoleOutputCharacter() failed!\n");
return 0;
}
/* Strip trailing whitepace (there should be a lot!)*/
while(num_chars_read && tbuff[num_chars_read-1] == ' ')
tbuff[--num_chars_read] = '\0';
/* Copy text to the clipboard*/
if (!copy_to_clipboard(tbuff))
{
free(tbuff);
printf("copy_to_clipboard() failed!\n");
return 0;
}
free(tbuff); /* Always free() */
/* Notify user done */
printf("All done. Success. Open notepad and paste from clipboard.\n");
_getch(); /* wait key press */
return 0;
}
Ваш код работает. Большое спасибо. Мне пришлось изменить «tbuff = malloc(size+1);» to "tbuff = (char *)malloc(size+1);" Но в остальном это то решение, которое я искал.
@BobPenoyer — отличные новости! Очень приветствую и спасибо, что выбрали мой ответ. При добавлении приведения для malloc()
: (char *)
-- да, некоторые компиляторы этого хотят. Не должны, но некоторые делают, лол. Это тема для другого дня. Удачного...
@gregspears «да, некоторым компиляторам нужен [приведение для malloc()
]» - точнее, каждый компилятор C не заботится об этом, и каждый компилятор C++ требует этого. В C void*
неявно преобразуется в любой другой тип указателя, но в C++ это не так.
В C и C++ нет понятия ни об окне консоли, ни о том, как с ним взаимодействовать. Мне не известен какой-либо Win32 API для чтения текста консоли, который не является пользовательским вводом, поэтому, если не считать использования Win32
SendInput()
для ручной имитации реальных событий мыши и клавиатуры, отправляемых в окно консоли, я не знаю ни одного другой способ сделать то, что вы хотите.