Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

   Программирование -> C++ Builder -> Немного о внешних устройствах и операционной системе


Немного о внешних устройствах и операционной системе

Наталия Елманова
Компьютер Пресс - CD, 1999, N 3
Copyright © N.Elmanova & ComputerPress Magazine.

В данной статье содержатся советы, позволяющие решить некоторые из множества проблем, возникающие при использовании внешних устройств в приложениях Delphi и С++Builder.

Определение наличия дискеты или компакт-диска в дисководе

Нередко в процессе работы приложения следует произвести запись на дискету или считать данные с компакт-диска. Во избежание возникновения сообщений об ошибке при отсутствии диска или дискеты либо об отсутствии свободного места на диске следует определить, готово ли устройство, и каков объем свободного пространства на нем.

Для получения информации о диске можно использовать функцию Windows API GetVolumeInformation. Эта функция возвращает информацию об имени и метке тома, а также характеристиках его файловой системы.

Для получения информации о наличии свободного места на диске можно использовать функцию GetDiskFreeSpace. Эта функция возвращает информацию о числе свободных кластеров и секторов и размерах сектора и кластера для данного диска. Число свободных байт равно числу свободных кластеров, умноженному на число секторовв кластере и на число байт в секторе.

Создадим простейший пример, определяющий тип устройства, его готовность и количество свободных байт. На форму приложения поместим компонент TDriveComboBox со страницы Win31 и четыре метки.

Рис. 1. Форма приложения для получения информации о дисках

Создадим обработчик события OnChange компонента TDriveComboBox. В случае C++Builder он выглядит следующим образом:

void __fastcall TForm1::DriveComboBox1Change(TObject *Sender)
{
DWORD VolSN,MaxCompLen,FSFlags, FC,SPC,BPS,NC;
char VolName[255],FSName[100];
AnsiString s=UpperCase(DriveComboBox1->Drive)+":\\";
Label1->Caption=s;
if (GetVolumeInformation(s.c_str(),VolName,255,&VolSN,&MaxCompLen, &FSFlags,FSName,100))
  {
   Label2->Caption="Имя тома: "+AnsiString(VolName);
   Label3->Caption="Файловая система: "+AnsiString(FSName);
   if (GetDiskFreeSpace(s.c_str(), &SPC,&FC,&BPS,&NC))
   {
     Label4->Caption="Свободных байт: "+IntToStr(SPC*FC*BPS);
   }
   else
   {
    Label4->Caption="";
   }
  }
else
  {
   Label2->Caption="Диск не готов";
   Label3->Caption="";
   Label4->Caption="";
  }
}

В случае Delphi этот же обработчик события выглядит так:

procedure TForm1.DriveComboBox1Change(Sender: TObject);
var
 VolName: array [0..255] of char;
 FSName : array [0..100] of char;
 VolSN: PDWORD;
 MaxCompLen,FSFlags: Cardinal;
 FC,SPC,BPS,NC:DWORD;
 s: string;
begin
 VolSN:=nil;
 s:=UpperCase(DriveComboBox1.Drive)+':\';
 Label1.Caption:=s;
 if (GetVolumeInformation(PChar(s),VolName,255,
 VolSN,   MaxCompLen, FSFlags,FSName,100)) then 
  begin
    Label2.Caption:='Имя тома: '+AnsiString(VolName);
    Label3.Caption:='Файловая система: '+AnsiString(FSName) ;
    if GetDiskFreeSpace(PChar(s),SPC,BPS,FC,NC) then
     Label4.Caption:='Свободных байт:  '+IntToStr(SPC*FC*BPS)
    else  Label4.Caption:=''
  end 
  else    
   begin
    Label2.Caption:='Диск не готов';
    Label3.Caption:='';
    Label4.Caption:=''
   end;
end;

Запустив приложение, мы можем выбирать устройство из списка доступных устройств и получать информацию о готовности устройства, метке тома и числе свободных байт.

Рис. 2. Приложение для вывода информации о дисках на этапе выполнения

Получение сведений о видеорежиме

Приложения, активно использующие работу с графикой или видеофрагментами, нередко нуждаются в информации о текущем цветовом разрешении видеоадаптера. Каким образом получить такие сведения?

Обычно для этой цели используется функция Windows API GetDeviceCaps, использующая в качестве входного параметра контекст графического устройства (каковым является экран). В данном примере мы воспользуемся обычной формой VCL для доступа к этому контексту, используя ее свойство Canvas.

В качестве второго параметра этой функции используется именованная целая константа, в зависимости от значения которой возвращается одно из значений, связанных с параметрами графического устройства. В данном случае нас интересуют цветовое разрешение в битах на пиксел и число поддерживаемых системой цветов. Последнее зависит от числа оттенков цвета. Число оттенков равно 2 в степени, равной цветовому разрешению в битах на пиксел. Число же поддерживаемых системой цветов равно числу оттенков, возведенному в степень, равную числу цветовых плоскостей. Следовательно, для вычисления числа поддерживаемых цветов функцию GetDeviceCaps следует вызвать дважды - один раз для получения информации о цветовом разрешении, другой раз - о числе цветовых плоскостей.

Создадим простейшее приложение для определения этих параметров. С этой целью поместим на форму кнопку и несколько меток.

Рис. 3. Форма приложения для определения цветового разрешения экрана.

Создадим обработчик события, связанный с нажатием на кнопку. В C++Builder он выглядит следующим образом:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 long int TC,BPP,CP,VR;
 BPP=GetDeviceCaps(Form1->Canvas->Handle,BITSPIXEL);
 CP=GetDeviceCaps(Form1->Canvas->Handle,PLANES);
 TC=pow(pow(2,BPP),CP);
 Label1->Caption="Бит на пиксел: "+IntToStr(BPP);
 if (TC<3) 
 {
   Label2->Caption="Монохромный дисплей ";
 } 
 else
 {
  Label2->Caption="Число цветов: "+IntToStr(TC);
 }  ;
}

Аналогичный код для Delphi имеет вид:

procedure TForm1.Button1Click(Sender: TObject);
Var    TC,BPP,CP,VR,x:  integer; x2:real;
begin
 BPP:=GetDeviceCaps(Form1.Canvas.Handle,BITSPIXEL);
 CP:=GetDeviceCaps(Form1.Canvas.Handle,PLANES);
 x2:=intpower(2,BPP);
 x2:=intpower(x2,CP); TC:=round(x2);
 Label1.Caption:='Бит на пиксел: '+IntToStr(BPP);
 if (TC<3) then  Label2.Caption:='Монохромный дисплей ' else
 Label2.Caption:='Число цветов: '+IntToStr(TC);
end;

Запущенное приложение выглядит примерно так:

Рис. 4. Приложение для определения цветового разрешения экрана.

Помимо цветового разрешения и числа поддерживаемых цветов c помощью функции GetDeviceCaps можно получить много другой информации о графических устройствах, например, о разрешении в пикселах на дюйм, числе поддерживаемых шрифтов и др. При работе в Windows NT можно даже определить частоту развертки монитора.

Получение сведений о частоте развертки монитора

Модифицируем ранее созданный пример, добавив определение типа операционной системы, и, если это Windows NT - определение частоты развертки. С этой целью необходимо в первую очередь определить тип операционной системы.

Как определить тип операционной системы? Для этой цели воспользуемся функцией Windows API GetVersionEx. Но, прежде чем ее вызвать, следует создать структуру типа OSVERSIONINFO, содержащую сведения об имении версии операционной системы (подробное описание этой структуры можно найти в справке по функциям Windows API, поставляемой с обоими средствами разработки), и корректно определить ее размер с помощью функции sizeof.

Поместим еще одну метку на форму нашего примера и изменим обработчик события, связанного с нажатием на кнопку: В случае C++Builder он теперь имеет вид:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 long int TC,BPP,CP,VR;
 OSVERSIONINFO OV;
 BPP=GetDeviceCaps(Form1->Canvas->Handle,BITSPIXEL);
 CP=GetDeviceCaps(Form1->Canvas->Handle,PLANES);
 TC=pow(pow(2,BPP),CP);
 Label1->Caption="Бит на пиксел: "+IntToStr(BPP);
 if (TC<3)
 {     
   Label2->Caption="Монохромный дисплей ";
 }  
 else
 {
  Label2->Caption="Число цветов: "+IntToStr(TC); 
 }  ;
 OV.dwOSVersionInfoSize=sizeof(OV);
 GetVersionEx(&OV);
 if (OV.dwPlatformId==VER_PLATFORM_WIN32_NT)
 {
  VR=GetDeviceCaps(Form1->Canvas->Handle,VREFRESH);
  Label3->Caption="Частота развертки: "+IntToStr(VR)+" Гц";
 }
 else
 {
  Label3->Caption="Частота развертки не определется в данной ОС";
 }
}

Соответствующий код для Delphi выглядит так:

procedure TForm1.Button1Click(Sender: TObject);
Var    TC,BPP,CP,VR,x:  integer; x1,x2:real;
OV: TOSVersionInfo;
begin
BPP:=GetDeviceCaps(Form1.Canvas.Handle,BITSPIXEL);
CP:=GetDeviceCaps(Form1.Canvas.Handle,PLANES);
x2:=intpower(2,BPP);
x2:=intpower(x2,CP); TC:=round(x2);
Label1.Caption:='Бит на пиксел: '+IntToStr(BPP);
if (TC<3) then  Label2.Caption:='Монохромный дисплей ' else
Label2.Caption:='Число цветов: '+IntToStr(TC);
OV.dwOSVersionInfoSize:=SizeOf(OV);
GetVersionEx(OV);
if OV.dwPlatformID=VER_PLATFORM_WIN32_NT then begin
VR:=GetDeviceCaps(Form1.Canvas.Handle,VREFRESH);
Label3.Caption:='Частота развертки: '+IntToStr(VR)+' Гц';
end else   Label3.Caption:='Частота развертки не определется в данной ОС';
end;
end.

Если запустить это приложение в операционной системе Windows NT, оно отобразит сведения о частоте развертки:

Рис. 5. Приложение для определения частоты развертки под управлением Windows NT

Рис. 6. То же приложение под управлением Windows 95

Инициирование перезагрузки Windows 95/98

Иногда в процессе работы приложения следует произвести перезагрузку операционной системы. Это бывает необходимо, если в процессе работы приложения были произведены изменения в переменных окружения, изменено сетевое имя компьютера, и др.

Для перезагрузки операционной системы можно использовать функцию Windows API ExitWindowsEx, первый из параметров которой определяет способ завершения работы Windows 95/98.

Создадим простейший пример, использующий эту функцию. Для этого на форму приложения поместим три кнопки:

Рис. 1. Форма приложения для инициирования перезагрузки Windows.

Создадим обработчики событий, связанных с нажатием на кнопки:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
ExitWindowsEx(EWX_LOGOFF,0);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
ExitWindowsEx(EWX_SHUTDOWN,0); 
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)
{
ExitWindowsEx(EWX_REBOOT,0);         
}
//---------------------------------------------------------------------------

В случае Delphi эти же обработчики событий выглядят так:

procedure TForm1.Button1Click(Sender: TObject);
begin
ExitWindowsEx(EWX_LOGOFF,0);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
ExitWindowsEx(EWX_SHUTDOWN,0); 
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
ExitWindowsEx(EWX_REBOOT,0);         
end;

Запустив приложение, мы можем выбрать способ завершения работы Windows либо сеанса пользователя Windows.

Отметим, что завершение работы или сеанса пользователя вWindows 95/98 действительно может быть осуществлено всеми тремя способами. В Windows NT же в общем случае работоспособен только первый обработчик события. Дело в том, что в соответствии с соображениями безопасности не всякое приложение имеет право произвести завершение работы Windows NT (например, хотя бы потому, что под управлением этой операционной системы могут выполняться различные сетевые и иные сервисы, жизненно важные для функционирования других компьютеров сети). Если же тем не менее возникнет необходимость произвести завершение работы Windows NT, а не просто завершение сеанса пользователя, следует воспользоваться функцией Windows API AdjustTokenPrivileges для предоставления данному приложению права остановки или перезагрузки операционной системы.

Отключение хранителя экрана

Нередко разработчики приложений, выполняющих какие-либо длительные действия (например, обработку большого количества данных или пересылку данных на удаленный компьютер с помощью низкоскоростной линии связи), сталкиваются с проблемами, создаваемыми так называемыми хранителями экрана (screen savers). Хранители экрана представляют собой, по существу, такие же Windows-приложения, нередко потребляющие немалое количество самых разнообразных ресурсов, за исключением собственно люминофора, которым покрыта внутренняя поверхность экрана монитора. Поэтому при запущенном хранителе экрана в общем случае производительность любого другого приложения, выполняющего какие-либо длительные действия, может существенно снизиться.

Чтобы понять, как предотвратить запуск хранителя экрана, следует вспомнить, что операционные системы с графическим пользовательским интерфейсом (в том числе Windows) основаны на посылке и обработке сообщений, а также на обработке событий. Windows постоянно обрабатывает разнообразные события, в том числе события, связанные с перемещением мыши или нажатием клавиш. Хранитель экрана запускается операционной системой, если по истечении заранее заданного (то есть установленного пользователем операционной системы) промежутка времени не происходило двух указанных выше типов событий. Для этого операционная система посылает активному приложению сообщение WM_SYSCOMMAND с параметром WPARAM, равным SC_SCREENSAVE. Именно это сообщение и следует перехватить в нашем приложении.

Перехват сообщения можно осуществить, создав обработчик события OnMessage объекта TApplication, наступающего при получении приложением очередного сообщения Windows. Соответствующая функция имеет два параметра: имя сообщения и параметр handled, указывающий, обрабатывается ли такое сообщение данным приложением. Если он установлен равным false, сообщение обрабатывается операционной системой. В противном случае оно обрабатывается приложением.

Создадим простейший пример, иллюстрирующий перехват такого сообщения. Для этого поместим на форму радиогруппу из двух элементов:

Рис. 2. Форма приложения для определения цветового разрешения экрана.

Теперь создадим функцию-член класса TForm1 (в C++Builder 4 для этого есть специальный эксперт, встроенный в Code Explorer, однако не возбраняется создать определение функции вручную):

Рис. 3. Создание новой функции-члена класса TForm1 с помощью C++Builder 4.

Создадим текст этой функции, а также обработчик события, связанный с созданием формы приложения и указывающий, какая функция должна вызываться при получении сообщения данным приложением:

void __fastcall TForm1::ProcessMess(TMsg & msg, bool &handled)
{
    //TODO: Add your source code here
    if (msg.message==WM_SYSCOMMAND && msg.wParam==SC_SCREENSAVE
        && RadioGroup1->ItemIndex==1)
handled=true;
else
handled=false;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
Application->OnMessage = ProcessMess;
}

Если функция создана вручную, следует не забыть создать ее определение в h-файле:

class TForm1 : public TForm
{
__published:	// IDE-managed Components
        TRadioGroup *RadioGroup1;
        void __fastcall FormCreate(TObject *Sender);
private:
    void __fastcall ProcessMess(TMsg & msg, bool &handled);
  public:		// User declarations
        __fastcall TForm1(TComponent* Owner);
};

Аналогичный код для Delphi имеет вид:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;
  
type
  TForm1 = class(TForm)
    RadioGroup1: TRadioGroup;
    procedure FormCreate(Sender: TObject);
      private
      procedure ProcessMess(var msg:TMsg; var handled:boolean) ;
    { Private declarations }
  public
    { Public declarations }
  end;
  
var
  Form1: TForm1;
  
implementation

{$R *.DFM}

{ TForm1 }
procedure TForm1.ProcessMess(var msg: TMsg; var handled: boolean);
begin
    if (msg.message=WM_SYSCOMMAND) and
   (msg.wParam=SC_SCREENSAVE)
    and (RadioGroup1.ItemIndex=1)    then
handled:=true
else
handled:=false;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage:=ProcessMess;
end;

end.

Если созданное таким образом приложение активно, хранитель экрана будет запускаться (или не запускаться) в зависимости от того, какая опция выбрана в радиогруппе.

Получение сведений об операционной системе

Нередко при разработке приложений требуется определить, какова версия операционной системы, где расположены системные каталоги, каковы значения переменных окружения. Для этой цели используются функции Windows API, такие как GetVersionEx (определение типа операционной системы), GetComputerName(определение сетевого имени компьютера), GetUserName (определение имени пользователя), GetSystemDirectory (определение местоположения системного каталога), GetWindowsDirectory (определение каталога Windows), ExpandEnvironmentStrings (определение значений переменных окружения), а также структуры Windows (например, OSVERSIONINFO). Подробные сведения об этих функциях и структурах содержатся в справке по Windows API, входящей в комплект поставки как C++Builder, так и Delphi.

Приведем простейший пример использования некоторых из этих функций, являющийся в значительной степени вариацией на тему стандартных примеров использования Windows API. Поместим на главную форму вновь созданного приложения несколько меток и кнопку и создадим обработчик события, связанный с нажатием на кнопку и отображающий системную информацию в метках:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
LPTSTR lpszSystemInfo;
DWORD cchBuff = 256;
TCHAR tchBuffer2[1000];
DWORD dwResult;
TCHAR tchBuffer[1000];
int nSize;

lpszSystemInfo = tchBuffer2;

GetComputerName(lpszSystemInfo, &cchBuff);
nSize = sprintf(tchBuffer, "Компьютер:  %s",  lpszSystemInfo);
Label1->Caption=AnsiString(tchBuffer);

GetUserName(lpszSystemInfo, &cchBuff);
nSize = sprintf(tchBuffer, "Пользователь:  %s", lpszSystemInfo);
Label2->Caption=AnsiString(tchBuffer);

nSize = GetSystemDirectory(lpszSystemInfo, MAX_PATH);
nSize = sprintf(tchBuffer, "System directory:  %s", lpszSystemInfo);
Label3->Caption=AnsiString(tchBuffer);

nSize = GetWindowsDirectory(lpszSystemInfo, MAX_PATH);
nSize = sprintf(tchBuffer, "Windows directory:  %s", lpszSystemInfo);
Label4->Caption=AnsiString(tchBuffer);
Label5->Caption="Переменные окружения :";

dwResult = ExpandEnvironmentStrings("OS=%OS% ", lpszSystemInfo, 500);
Label6->Caption=AnsiString(lpszSystemInfo);

dwResult = ExpandEnvironmentStrings("INCLUDE=%INCLUDE%",lpszSystemInfo,500);
Label7->Caption=AnsiString(lpszSystemInfo);

dwResult = ExpandEnvironmentStrings("CLASSPATH=%CLASSPATH%",lpszSystemInfo,500);
Label8->Caption=AnsiString(lpszSystemInfo);

dwResult = ExpandEnvironmentStrings("ComSpec=%ComSpec%",lpszSystemInfo,500);
Label9->Caption=AnsiString(lpszSystemInfo);

OSVERSIONINFO osvi;
char szVersion [80];
  
memset(&osvi, 0, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&osvi);

if (osvi.dwPlatformId == VER_PLATFORM_WIN32s)
    wsprintf (szVersion, "Microsoft Win32s %d.%d (Build %d)",
        osvi.dwMajorVersion,
        osvi.dwMinorVersion,
        osvi.dwBuildNumber & 0xFFFF);

else if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
    wsprintf (szVersion, "Microsoft Windows 95 %d.%d (Build %d)",

		osvi.dwMajorVersion,
        osvi.dwMinorVersion,
        osvi.dwBuildNumber & 0xFFFF);

else if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
    wsprintf (szVersion, "Microsoft Windows NT %d.%d (Build %d)",

		osvi.dwMajorVersion,
        osvi.dwMinorVersion,
        osvi.dwBuildNumber & 0xFFFF);
Label10->Caption="Операционная система: "+AnsiString(szVersion);
}

Соответствующий код для Delphi выглядит так:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;
  
type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  
var
  Form1: TForm1;
  
implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var osvi: TOSVersionInfo;  si: TSystemInfo;
s:string;
dwResult, nsize: Cardinal;
ch : array[0..1000] of Char;
begin

GetComputerName(ch, nsize);
Label1.Caption:='Компьютер: '+ch;

GetUserName(ch, nsize);
Label2.Caption:='Пользователь: '+ch;

nSize := GetSystemDirectory(ch, MAX_PATH);
Label3.Caption:='System directory: '+ch;

nSize := GetWindowsDirectory(ch, MAX_PATH);
Label4.Caption:='Windows directory: '+ch;

Label5.Caption:='Переменные окружения :';

dwResult:= ExpandEnvironmentStrings('OS=%OS% ', ch, 500);
Label6.Caption:=ch;

dwResult:= ExpandEnvironmentStrings('INCLUDE=%INCLUDE%',ch,500);
Label7.Caption:=ch;

dwResult:= ExpandEnvironmentStrings('CLASSPATH=%CLASSPATH%',ch,500);
Label8.Caption:=ch;

dwResult := ExpandEnvironmentStrings('ComSpec=%ComSpec%',ch,500);
Label9.Caption:=ch;

osvi.dwOSVersionInfoSize := sizeof (OSVERSIONINFO);
GetVersionEx (osvi);

if (osvi.dwPlatformId = VER_PLATFORM_WIN32s) then
s:= 'Microsoft Win32s '+IntToStr(osvi.dwMajorVersion)+'.'+
IntToStr(osvi.dwMinorVersion) +' Build '+
IntToStr(osvi.dwBuildNumber);

if (osvi.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS)
then
s:= 'Microsoft Windows 95 '+IntToStr(osvi.dwMajorVersion)+'.'+
 IntToStr(osvi.dwMinorVersion) +' Build '+
IntToStr(osvi.dwBuildNumber);

if (osvi.dwPlatformId = VER_PLATFORM_WIN32_NT)
then
s:= 'Microsoft Windows NT '+IntToStr(osvi.dwMajorVersion)+'.'+
IntToStr(osvi.dwMinorVersion) +' Build '+
IntToStr(osvi.dwBuildNumber);

Label10.Caption:=' Операционная система: '+s;

end;

end.

Если запустить это приложение, оно отобразит сведения о системе и переменных окружения:

Рис. 4. Приложение для вывода сведений о системе

Отметим, что в настоящее время имеется немалое количество свободно распространяемых, условно-бесплатных и коммерческих компонентов для Delphi и C++Builder, предназначенных для получения системной информации (некоторые из них содержатся на компакт-диске в данном номере журнала). Все они так или иначе используют те же самые функции Windows API для установки или считывания значений своих свойств или выполнения методов, и основное их преимущество заключается главным образом в том, что они избавляют программиста от необходимости создания кода, подобного приведенному выше. Соответственно при разработке приложений можно использовать как непосредственно функции Windows API, как в приведенных выше примерах, так и готовые компоненты.

 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.