Редактор буфера обмена
Определение буфера обмена, его расположение, правила работы, форматы хранимых данных. WIN API функции, используемые в данном проекте. Модульная структура программы, краткое описание подпрограмм и их назначение, причины использования многопоточности.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 24.06.2011 |
Размер файла | 872,5 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
Введение
Создание и редактирование документов, копирование файлов и папок - эти, казалось бы, простейшие действия очень тяжело, а порой невозможно, совершать без буфера обмена. Также нередко требуется редактировать данные уже помещённые в буфер обмена. А чтобы что-то изменить, то это сначала нужно увидеть. Именно это и будет реализовано в данном курсовом проекте: просмотр и редактирование содержимого буфера обмена.
Данный курсовой проект можно разбить на 3 главы.
В первой главе дано определение буферу обмена, сказано о теоретических основах, где он располагается, как с ним работать, какие форматы данных он может хранить. Также в этой главе сказано о WIN API функциях, которые используются в данном проекте.
Вторая глава посвящена разработке. Здесь описана модульная структура программы, дано краткое описание основных подпрограмм и их назначение, также сказано о причинах использовании многопоточности в программе.
Третья глава - Тестирование. Здесь сказано о том, как работает программа, на каких данных. Также в этой главе приведены копии экрана, отображающие работу программы.
1. Теоретические основы
1.1 Буфер обмена
Буфер обмена - область оперативной памяти компьютера, в которой могут сохраниться данные различных форматов для переноса или копирования их между приложениями или частями одного приложения.
Если же посмотреть на буфер обмена с программной точки зрения, то можно дать такое определение:
Буфер обмена - это набор функций и сообщений, который позволяет приложениям сохранять в памяти, данные и передавать их между разными приложениями. Объект в буфере обмена может быть представлен в любом формате данных, называемом форматом буфера обмена. Каждый формат определён целым значением. Для стандартных форматов буфера обмена эти значения являются константами, определёнными в Win32 API.
Чтобы окончательно разобраться, чем является буфер обмена и каковы его роли в операционной системе, проведём некоторую аналогию между буфером обмена и ячейкой склада, куда отправляется на временное хранение некий объект. В этой ячейке можно хранить лишь один объект. Чтобы поместить в ячейку новый объект, необходимо убрать из нее старый объект, ранее помещенный туда. В буфере обмена объект хранится до тех пор, пока в него не будет помещен новый объект, который автоматически сотрет прежний. Находящийся в буфере обмена объект можно копировать неограниченное количество раз.
Буфер обмена обслуживается операционной системой и характеризуется следующими свойствами:
в буфере обмена хранится объект, помещенный в него одним из известных пользователю способов;
в буфере обмена объект хранится до тех пор, пока не будет помещен в него новый объект;
буфер обмена доступен из любого приложения;
буфер обмена очищается при перезагрузке операционной системы либо специальной функцией;
объект в буфере обмена хранится в формате, определяемом приложением-источником, но при его вставке в составной документ, как правило, предоставляется возможность преобразования в другой формат.
Моей целью в данном курсовом проекте является создание редактора буфера обмена. Этот программный продукт позволит просматривать данные, находящиеся в буфере и редактировать их.
1.2 Форматы данных буфера обмена
Буфер обмена может хранить множество различных форматов данных. Некоторые используются пользователями, а некоторые предназначены для конкретных приложений. К тому же, средствами WIN API можно формировать свои форматы данных.
В данном курсовом проекте я сделаю возможность просматривать только три самых используемых пользователями формата: CF_TEXT, CF_HDROP, CF_BITMAP.
CF_TEXT - текстовый формат данных. Возможно редактировать с помощью программы notepad(Блокнот).
CF_BITMAP - графический формат данных. Возможно редактировать с помощью программы mspaint.
CF_HDROP - Дескриптор типа HDROP - это тот, который идентифицирует список файлов. Прикладная программа может извлечь информацию о файлах, передавая дескриптор функции DragQueryFile().
1.3 Используемые WIN API функции.
В проекте используется несколько WIN API функций. Конечно, в силу специфики программы, многие из них предназначены для работы с буфером обмена.
BOOL OpenClipboard (HWND hWndNewOwner);
Функция предназначена для открытия буфера обмена. Входным параметром является дескриптор окна, для которого буфер обмена будет открыт. Если передать дескриптор окна равным 0, то буфер обмена будет открыт для текущего окна. При удачном выполнении возвращает ненулевое значение.
BOOL EmptyClipboard(VOID);
Данная функция не имеет входных параметров и предназначена для очистки буфера обмена. При удачном выполнении возвращает ненулевое значение.
HANDLE GetClipboardData (UINT uFormat);
Возвращает дескриптор на данные формата, который указан как входной параметр. В данном курсовом проекте используются 3 формата: CF_TEXT, CF_HDROP, CF_BITMAP.
BOOL CloseClipboard(VOID);
Закрывает открытый ранее буфер обмена. При удачном выполнении возвращает ненулевое значение.
HANDLE SetClipboardData (UINT uFormat, HANDLE hMem);
Устанавливает данные, имеющие дескриптор hMem и формата uFormat в буфер обмена. При удачном завершении, функция вернёт дескриптор на эти же данные.
BOOL IsClipboardFormatAvailable (UINT format);
Данная функция возвращает ненулевое значение если формат данных в буфере обмена совпадает с форматом, указанным как входной параметр.
Также существуют другие функции, предназначенные для работы с буфером обмена, но они в проекте не используются и в подробном рассмотрении не нуждаются.
Другие WIN API функции используемые в проекте:
LPVOID WINAPI GlobalLock (HGLOBAL hMem);
Блокирует объект в памяти и возвращает указатель на его первый байт.
BOOL WINAPI GlobalUnlock (HGLOBAL hMem);
Разблокирует ранее заблокированный объект. В случае удачного завершения возвращает не нулевое значение.
UINT DragQueryFile (HDROP hDrop, UINT iFile, LPTSTR lpszFile, UINT cch);
Используется мной для перечисления имён файлов, скопированных в буфер обмена (в том случае, если скопированы файлы, а не их части), т.е. когда формат буфера обмена равен константе, CF_HDROP.
HANDLE WINAPI CreateFile (LPCTSTR lpFileName, DWORD dwDesiredAccess, dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, opt HANDLE hTemplateFile);
Создаёт файл с заданным именем (первый параметр) и открывает его. Мной используется для создания временных файлов, которые потом удаляются.
BOOL WINAPI DeleteFile (LPCTSTR lpFileName);
Удаляет файл с заданным именем.
BOOL WINAPI WriteFile / ReadFile
Имеют схожие параметры. Служат для записи в файл и для чтения из него.
BOOL WINAPI CreateProcess();
Создаёт процесс. Используется мною для открытия текстового или графического редакторов.
DWORD WINAPI WaitForSingleObject (HANDLE hHandle, DWORD dwMilliseconds);
Функция, которая переводит поток, вызвавший её в ожидание сообщения от объекта hHandle. Используется в проекте для ожидания завершения редактирования.
HANDLE WINAPI CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
Создаёт поток в виртуальном адресном пространстве процесса. Параметр lpStartAddress является указателем на функцию определённого вида.
BOOL WINAPI CloseHandle (HANDLE hObject);
Закрывает открытый ранее дескриптор. При удачном завершении возвращает ненулевое значение.
2. Разработка и реализация программы
2.1 Модульная структура программы
Программа содержит три модуля, а модульную структуру программы можно представить следующей схемой:
буфер обмен программа многопоточность
Стрелками показана очерёдность использования модулей при запуске приложения.
Модуль ClipboardEditor.cpp содержит в себе функцию WinMain(), которая вызывает функции создания приложения и формы, описания которых содержаться в заголовочном файле Unit1.h, реализация методов, описанных в этом файле, находится в Unit1.cpp. Этот модуль подробнее будет рассмотрим позже.
2.2 Модуль Unit1.cpp
В этом модуле содержится реализация всех методов формы, которую использует приложение, а также дополнительных функций. Эти самые дополнительные функции и выполняют основные действия по отображению и редактированию (на самом же деле вызова Notepad.exe или MsPaint.exe) буфера обмена. Вот заголовки и краткие спецификации этих самых дополнительных функций:
DWORD WINAPI read_text (void *p);
Читает текст из буфера и отображает его в поле вывода.
DWORD WINAPI read_link (void *p);
Читает названия файлов, скопированных в буфер, и отображает их в поле вывода.
DWORD WINAPI read_bmp (void *p);
Читает картинку из буфера и отображает её в поле вывода.
DWORD WINAPI edit_text (void *p);
Вызывается для редактирования текстовых данных. Именно в этой функции содержиться запуск программы Notepad.exe и ожидание её закрытия.
DWORD WINAPI edit_bmp (void *p);
Вызывается для редактирования изображений. Именно в этой функции содержится запуск программы MsPaint.exe и ожидание её закрытия.
В каждой из этих функций есть входной параметр, который на самом деле не используется в теле функций. Он нужен для того, чтобы каждая из функций была «пригодна» для запуска её в отдельном потоке.
Также стоит отметить особенности работы функций редактирования: каждая из функций сначала создаёт файл, затем открывает буфер обмена, считывает из него данные, закрывает буфер обмена, записывает данные в файл, затем открывает необходимое приложение, ждёт его завершения и потом уже из файла помещает данные в буфер обмена. Заметим, что во время ожидания завершения редактирования (на самом деле приложения), буфер обмена не принадлежит ни одному окну, что позволяет использовать его во время редактирования его же содержимого.
2.3 Многопоточность
В программе реализована многопоточность. Потоки создаются в двух случаях: чтобы отобразить содержимое буфера обмена и чтобы отредактировать это содержимое. Выполнение основных функций программы различными потоками позволяет «разгрузить» основной поток программы, он не находится длительное время в режиме ожидания. Этот поток, можно сказать, отвечает за прорисовку окна и кнопок программы. Также существуют ещё 2 потока, один из них создаётся при отображении содержимого буфера обмена, а другой - при редактировании. Если бы не было многопоточности, то программа во время редактирования данных находилась бы в состоянии ожидания, и не было бы возможности даже свернуть или переместить её. Также использование многопоточности в общем ускоряет работу программы.
3. Тестирование
3.1 Тестовые данные
Воспользуемся тремя видами тестовых данных.
Текстовый, например текст «Hello!»
Ярлык С++Builder в меню пуск.
Копия экрана в какой-то момент времени.
Каждый раз, при тестировании, нужно помещать в буфер обмена данные. В первых двух случаях с помощью мыши. В третьем случае с помощью клавиши Prt Sc на клавиатуре.
Для первого и третьего тестов, которые можно редактировать, покажем результаты некоторого редактирования. Они представлены ниже в виде копий экрана.
3.2 Копии экрана
Сначала скопируем текст. В окне программы появится:
Нажмём на кнопку редактировать и отредактируем текст:
Теперь в буфере обмена хранится уже изменённый текст.
Скопируем ярлык. Программа покажет:
Данный формат невозможно редактировать средствами данного проекта.
Сделаем копию экрана:
В окне вывода видна копия экрана. Нажав на кнопку редактировать, откроется графический редактор mspaint. Изменив рисунок, сохраним его:
Заключение
Мною разработан программный продукт, который позволяет просматривать и редактировать данные буфера обмена. В программе используется несколько WIN API функций, реализована многопоточность. В пояснительной записке к курсовому проекту подробно расписаны все этапы разработки программы и приведены результаты работы программы в виде копий экрана.
Список литературы
1. Н.В. Майстренко, А.В. Майстренко. Программное обеспечение САПР. Операционные системы: учебное пособие - Тамбов: Изд-во Тамб. гос. техн. ун-та, 2007. - 76 с.
2. Таненбаум Э. Современные операционные системы. 2-е изд.-СПб.: Питер, 2002.-1040 с.
3. Джеффери Рихтер. Windows для профессионалов: создание эффективных win32 приложений. - 4-е изд. СПб.:Питер 2001.-752 с.
4. Библиотека MSDN [Электронный ресурс]/ Компания microsoft. Режим доступа: http://msdn.microsoft.com, свободный.
Приложение
Текст модуля ClipboardEditor.cpp:
#include <vcl.h>
#pragma hdrstop
// -
USEFORM («Unit1.cpp», Form1);
// -
WINAPI WinMain (HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->Title = «Clipboard Editor»;
Application->CreateForm (__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
catch (…)
{
try
{
throw Exception(«»);
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
}
return 0;
}
Текст модуля Unit1.h:
#ifndef Unit1H
#define Unit1H
// -
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
// -
class TForm1: public TForm
{
__published: // IDE-managed Components
TButton *Button2;
TButton *Button4;
TTimer *Timer1;
TImage *Im;
TButton *Button6;
TMemo *Memo1;
void __fastcall Button2Click (TObject *Sender);
void __fastcall Button4Click (TObject *Sender);
void __fastcall FormCreate (TObject *Sender);
void __fastcall FormDestroy (TObject *Sender);
void __fastcall Button6Click (TObject *Sender);
void __fastcall Timer1Timer (TObject *Sender);
private: // User declarations
public: // User declarations
void __fastcall Show(void);
__fastcall TForm1 (TComponent* Owner);
};
// -
extern PACKAGE TForm1 *Form1;
// -
#endif
Текст модуля Unit1.cpp:
#include <vcl.h>
#pragma hdrstop
#include «Unit1.h»
// -
#pragma package (smart_init)
#pragma resource «*.dfm»
const OS_TEXT = CF_TEXT;
const OS_LINK = CF_HDROP;
const OS_BMP = CF_BITMAP;
TForm1 *Form1;
HANDLE thread1, thread2; // 1-otobrajenie, 2-redactirovanie
static AnsiString FileName= «os_temp.»;
static AnsiString PaintFileName= «C:\\Windows\\System32\\mspaint.exe»;
static AnsiString NotepadFileName= «C:\\Windows\\notepad.exe»;
// -
__fastcall TForm1:TForm1 (TComponent* Owner)
: TForm(Owner){}
DWORD WINAPI read_text (void *p)
{
if (OpenClipboard(0))
{
HANDLE hData = GetClipboardData (CF_TEXT);
char* chBuffer= (char*) GlobalLock(hData);
GlobalUnlock(hData);
CloseClipboard();
Form1->Memo1->Lines->Clear();
Form1->Memo1->Lines->SetText(chBuffer);
Form1->Memo1->Visible=true;
Form1->Button6->Enabled=true;
}
return 1;
}
DWORD WINAPI read_link (void *p)
{AnsiString a=»»; int k;
if (OpenClipboard(0)) // открываем буфер обмена
{
HANDLE hData = GetClipboardData (CF_HDROP);
HDROP hh;
char s[100];
hh=hData;
CloseClipboard();
Form1->Memo1->Lines->Clear();
k=DragQueryFile (hh, 0xFFFFFFFF, s, 100);
for (int i=0; i < k; i++)
{
s[0]=0;
DragQueryFile (hh, i, s, 100);
a=AnsiString(s);
Form1->Memo1->Lines->Add(a);
}
Form1->Memo1->Visible=true;
Form1->Button6->Enabled=false;
}
return 1;
}
DWORD WINAPI read_bmp (void *p)
{
if (OpenClipboard(0)) {
HANDLE h = GetClipboardData (CF_BITMAP);
Form1->Im->Picture->LoadFromClipboardFormat (CF_BITMAP, (unsigned) h, 0);
CloseClipboard();
Form1->Im->Visible=true;
Form1->Button6->Enabled=true;
}
return 1;
}
DWORD WINAPI edit_text (void *p)
{
HGLOBAL hgBuffer;
char* chBuffer;
char r[100];
unsigned lr=100; DWORD k=0;
AnsiString inbuf=»»;
HANDLE f=0;
STARTUPINFO stinf={0};
_PROCESS_INFORMATION pr_inf;
stinf.cb=sizeof(STARTUPINFO);
stinf.dwXCountChars=50;
stinf.dwYCountChars=50;
stinf.dwFlags= STARTF_USECOUNTCHARS;
AnsiString s=FileName + «txt»;
f=CreateFile (s.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
NULL, NULL);
if (f==INVALID_HANDLE_VALUE) {ShowMessage («Error file open»); return 0;}
WriteFile (f, Form1->Memo1->Text.c_str(),
Form1->Memo1->Text. Length()+1,&k, 0);
CloseHandle(f);
s=NotepadFileName+s;
if (! CreateProcess(0, s.c_str(), 0,0, false, 0,0,0,&stinf,&pr_inf))
ShowMessage («ne zapuschen…»);
WaitForSingleObject (pr_inf.hProcess, INFINITE);
f=CreateFile((FileName+ «txt»).c_str(), GENERIC_READ,
0, NULL, OPEN_ALWAYS, NULL, NULL);
r[0]=0;
inbuf=»»;
while (ReadFile(f, r, lr,&k, 0)) {
if (k==0) break;
inbuf=inbuf+AnsiString(r);
r[0]=0;
}
CloseHandle(f);
if (! OpenClipboard(0)) {ShowMessage(«((»); return 1;}
EmptyClipboard();
hgBuffer= GlobalAlloc (GMEM_DDESHARE, inbuf. Length()+1);
chBuffer= (char*) GlobalLock(hgBuffer); // блокируем память
strcpy (chBuffer, inbuf.c_str());
GlobalUnlock(hgBuffer); // разблокируем память
SetClipboardData (CF_TEXT, hgBuffer); // помещаем текст в буфер обмена
CloseClipboard();
DeleteFile((FileName+ «txt»).c_str());
return 1;
}
DWORD WINAPI edit_bmp (void *p)
{
unsigned short MyClipboardFormat;
HANDLE MyHandle;
HPALETTE MyPalette;
HANDLE f;
STARTUPINFO stinf={0};
_PROCESS_INFORMATION pr_inf;
stinf.cb=sizeof(STARTUPINFO);
stinf.dwXCountChars=50;
stinf.dwYCountChars=50;
stinf.dwFlags= STARTF_USECOUNTCHARS;
AnsiString s=FileName + «bmp»;
Form1->Im->Picture->SaveToFile(s);
s=PaintFileName+s;
if (! CreateProcess(0, s.c_str(), 0,0, false, 0,0,0,&stinf,&pr_inf))
ShowMessage («ne zapuschen…»);
WaitForSingleObject (pr_inf.hProcess, INFINITE);
Form1->Im->Picture->LoadFromFile (FileName + «bmp»);
if (! OpenClipboard(0)) {return 1;}
EmptyClipboard();
MyHandle=Form1->Im->Canvas->Handle;
MyPalette=Form1->Im->Picture->Bitmap->Palette;
MyClipboardFormat=OS_BMP;
Form1->Im->Picture->Bitmap->SaveToClipboardFormat (MyClipboardFormat,
(unsigned) MyHandle, MyPalette);
SetClipboardData (MyClipboardFormat, MyHandle);
CloseClipboard();
DeleteFile((FileName+ «bmp»).c_str());
return 1;
}
void __fastcall TForm1: Button2Click (TObject *Sender)
{Application->Terminate();}
// -
void __fastcall TForm1: Button4Click (TObject *Sender)
{DWORD id=WaitForSingleObject (thread2,1);
if (id == WAIT_TIMEOUT) {ShowMessage («Snachala zavershite redactirovanie»);
return;}
if (! OpenClipboard(0)) {ShowMessage(«((»); return;}
EmptyClipboard();
CloseClipboard();
Form1->Memo1->Visible=false;
Form1->Im->Visible=false;
Form1->Button6->Enabled=false;
}
// -
void __fastcall TForm1: FormCreate (TObject *Sender)
{Show();}
void __fastcall TForm1: FormDestroy (TObject *Sender)
{CloseHandle(thread1); CloseHandle(thread2);}
// -
void __fastcall TForm1: Button6Click (TObject *Sender)
{
DWORD id=WaitForSingleObject (thread2,1);
if (id!= WAIT_TIMEOUT) {
if (IsClipboardFormatAvailable(OS_TEXT))
thread2=CreateThread (NULL, 0, edit_text, NULL, 0,&id);
else
if (IsClipboardFormatAvailable(OS_BMP))
thread2=CreateThread (NULL, 0, edit_bmp, NULL, 0,&id);
}
else ShowMessage («snachalo Zaverhite Redactirovanie»);
}
// -
void __fastcall TForm1: Show(void)
{DWORD id=WaitForSingleObject (thread2,1);
if (id!= WAIT_TIMEOUT) {
Memo1->Visible=false;
Im->Visible=false;
if (IsClipboardFormatAvailable(OS_TEXT))
thread1=CreateThread (NULL, 0, read_text, NULL, 0,&id);
else
if (IsClipboardFormatAvailable(OS_LINK))
thread1=CreateThread (NULL, 0, read_link, NULL, 0,&id);
else
if (IsClipboardFormatAvailable(OS_BMP))
thread1=CreateThread (NULL, 0, read_bmp, NULL, 0,&id);
}
}
void __fastcall TForm1: Timer1Timer (TObject *Sender)
{Show();}
Размещено на Allbest.ru
Подобные документы
Назначение буфера обмена, управление его данными в среде Windows. Взаимодействие между владельцем и клиентом буфера. Данные и тип дескриптора, для каждого типа предопределенных форматов. Воспроизведение данных буфера обмена с задержкой, окна просмотра.
реферат [58,9 K], добавлен 04.10.2010Характеристика буфера обмена как области памяти, резервируемой системой Windows для организации обмена данными между приложениями. Копирование и перемещение файлов как функции буфера обмена. Изучение абсолютной и относительной адресации ячеек MS Excel.
контрольная работа [13,9 K], добавлен 11.09.2011Классификация и основное назначение служебных программных средств (утилитов). Краткая характеристика дополнительных служебных компьютерных программ. Процедура использования буфера обмена в Windows. Использование автоформата в программе MS Excel.
контрольная работа [16,1 K], добавлен 08.12.2010Общие сведения о текстовом редакторе Microsoft Word. Основные операции редактора по работе с документами. Запуск программы, средства редактирования. Ввод и исправление текста, использование буфера обмена, форматирование абзацев, работа со шрифтами.
контрольная работа [25,5 K], добавлен 12.03.2011Понятие информационной и файловой систем. Пути заражения компьютера вирусом. Функции буфера обмена и оперативной памяти. Ключ в базе данных, использование ее функций для проведения анализа показателей финансово-экономической деятельности предприятий.
контрольная работа [2,2 M], добавлен 19.10.2012Рабочая книга, работа со строками и столбцами, адресация ячеек. Ввод, редактирование, форматирование данных. Вычисления в электронных таблицах. Абсолютные и относительные ссылки. Применение буфера обмена при копировании. Использование стандартных функций.
практическая работа [342,6 K], добавлен 31.01.2013Просмотр, запись и чтение данных буфера обмена. Динамический обмен данными (DDE), способы его организации. Атомы в Windows, их понятие и функции. Особенности задания параметра lParam сообщений DDE. Обмен и передача данных между клиентом и сервером.
лекция [303,7 K], добавлен 24.06.2009Обзор пакетов программ, предназначенных для визуализации и анализа данных. Обоснование выбора среды программирования. Организация аварийного буфера. Передача данных от нижнего уровня к верхнему и сохранение данных. Отображение данных в графической форме.
дипломная работа [512,4 K], добавлен 28.08.2012Определение назначения и описание функций дискового кэша как промежуточного буфера с быстрым доступом к информации. Процесс кэширования внешних накопителей. Построение алгоритма, описание интерфейса и разработка программы для работы с двусвязным списком.
курсовая работа [2,1 M], добавлен 21.01.2014Основные устройства, входящие в состав компьютера. Краткий обзор операционных систем. Рабочий стол и его структура. Запуск стандартных программ. Создание и перемещение папок и файлов с помощью буфера обмена и мыши. Просмотр ресурсов локальной сети.
отчет по практике [3,0 M], добавлен 02.10.2012