Практика
Скрываем диски в Explorer'е

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика


Интересно, много ли осталось людей, использующих Explorer в качестве основного файлового менеджера. Лично я уже забыл, когда последний раз пользовался им. Эта статья заинтересует в первую очередь тех людей, которые хотя бы иногда используют проводник. Сегодня я расскажу, каким образом можно скрывать в проводнике "ненужные" диски. Кстати, из этого вполне может получиться неплохая программа-прикол: включает друг компьютер, запускает Explorer, а дисков нет, испарились.

Этот нехитрый трюк можно выполнить, воспользовавшись реестром. Все, что для этого нужно, просто добавить к ветви реестра HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer двоичный ключ с именем 'NoDrives' и значением из соответствующей строки (значения строк приведены ниже). А если надо "спрятать" несколько дисков, то достаточно сложить строки. Только учтите, что значения шестнадцатеричные!

{A:\} 01 00 00 00      {N:\} 00 20 00 00
{B:\} 02 00 00 00      {O:\} 00 40 00 00
{C:\} 04 00 00 00      {P:\} 00 80 00 00
{D:\} 08 00 00 00      {Q:\} 00 00 01 00
{E:\} 10 00 00 00      {R:\} 00 00 02 00
{F:\} 20 00 00 00      {S:\} 00 00 04 00
{G:\} 40 00 00 00      {T:\} 00 00 08 00
{H:\} 80 00 00 00      {U:\} 00 00 10 00
{I:\} 00 01 00 00      {V:\} 00 00 20 00
{J:\} 00 02 00 00      {W:\} 00 00 40 00
{K:\} 00 04 00 00      {X:\} 00 00 80 00
{L:\} 00 08 00 00      {Y:\} 00 00 00 01
{M:\} 00 10 00 00      {Z:\} 00 00 00 02

Так как работать нам предстоит с реестром, добавим в uses модуль Registry, и определим ключ реестра. А чтобы иметь возможность перезагрузить Explorer, добавим модуль ShellAPI.

uses
  {...}, Registry, ShellAPI;

{...}

const
  HKEY = 'Software\Microsoft\Windows\CurrentVersion\Policies\Explorer';

Числовые значения для каждого диска от A:\ до Z:\ принадлежат диапазону от 20 до 225 соответственно. В приведенной ниже таблице показано, каким образом получается эта последовательность чисел, и как этот процесс можно автоматизировать.

{A:\} $00000001 = ( 1 shl 0 )       {N:\} $00002000 = ( 1 shl 13 )
{B:\} $00000002 = ( 1 shl 1 )       {O:\} $00004000 = ( 1 shl 14 )
{C:\} $00000004 = ( 1 shl 2 )       {P:\} $00008000 = ( 1 shl 15 )
{D:\} $00000008 = ( 1 shl 3 )       {Q:\} $00010000 = ( 1 shl 16 )
{E:\} $00000010 = ( 1 shl 4 )       {R:\} $00020000 = ( 1 shl 17 )
{F:\} $00000020 = ( 1 shl 5 )       {S:\} $00040000 = ( 1 shl 18 )
{G:\} $00000040 = ( 1 shl 6 )       {T:\} $00080000 = ( 1 shl 19 )
{H:\} $00000080 = ( 1 shl 7 )       {U:\} $00100000 = ( 1 shl 20 )
{I:\} $00000100 = ( 1 shl 8 )       {V:\} $00200000 = ( 1 shl 21 )
{J:\} $00000200 = ( 1 shl 9 )       {W:\} $00400000 = ( 1 shl 22 )
{K:\} $00000400 = ( 1 shl 10 )      {X:\} $00800000 = ( 1 shl 23 )
{L:\} $00000800 = ( 1 shl 11 )      {Y:\} $01000000 = ( 1 shl 24 )
{M:\} $00001000 = ( 1 shl 12 )      {Z:\} $02000000 = ( 1 shl 25 )

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin
   for i := 0 to 25 do
      ShowMessage( Format( '%.8x', [1 shl i] ) );
end;

Теперь все, что нам остается, это выбрать диски, которые мы хотим отключить, высчитать результатирующее число и записать его в реестр. Выбор дисков в моем примере осуществляется путем включения или отключения соответствующих CheckBox'ов. Чтобы изменения вступили в силу без перезагрузки компьютера, установите соответствующий флажок внизу формы.

procedure TForm1.ApplyClick(Sender: TObject);
var
  i: integer;
  d: DWord;
  hwndShell: HWND;
begin
   d := 0;
   for i := 0 to 25 do
      if TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Checked then
         d := d + ( 1 shl i );
   Reg := TRegistry.Create;
   Reg.RootKey := HKEY_CURRENT_USER;
   Reg.OpenKey( HKEY, false );
   Reg.WriteBinaryData( 'NoDrives', d, SizeOf( d ) );
   Reg.Free;

   // Если установлен флажок, перегружаем Explorer
   if RestartExplorer.Checked then
   begin
      hwndShell := FindWindow( 'Progman', nil );
      PostMessage( hwndShell, WM_QUIT, 0, 0 );
      ShellExecute( 0, 'open', 'Explorer', nil, nil, SW_SHOWNORMAL );
   end;

   Apply.Enabled := false;
end;

Чтобы при старте приложения знать, какие диски являются скрытыми в Explorer'е, напишем в событии OnCreate формы следующий код:

procedure TForm1.FormCreate(Sender: TObject);
var
  d: DWORD;
  i: byte;
begin
   d := 0;
   Reg := TRegistry.Create;
   Reg.RootKey := HKEY_CURRENT_USER;
   Reg.OpenKey( HKEY, true );
   if not Reg.ValueExists( 'NoDrives' ) then
      Reg.WriteBinaryData( 'NoDrives', d, SizeOf( d ) )
   else
      Reg.ReadBinaryData( 'NoDrives', d, SizeOf( d ) );
      if d <> 0 then
      begin
         for i := 0 to 25 do
            if ( d and ( 1 shl i ) ) = ( 1 shl i ) then
               TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Checked := true;
      end;
   Reg.Free;
end;

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

(* Показать только существующие диски *)
procedure TForm1.ShowAllReallyDiskClick(Sender: TObject);
  function DriveExists( Drive: Byte ): boolean;
  begin
     Result := ( GetLogicalDrives and ( 1 shl Drive ) ) <> 0;
  end;
var
  i: byte;
begin
   for i := 0 to 25 do
      if not DriveExists( i ) then
      begin
         TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Checked := false;
         TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Enabled := false;
      end;
end;

(* Показать все диски *)
procedure TForm1.ShowAllDiskClick(Sender: TObject);
var
  i: byte;
begin
   for i := 0 to 25 do
      TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Enabled := true;
end;

Также можно порадовать пользователя несколькими функциями, облегчающими процесс выбора дисков. Реализуем следующие возможности: "Выделить все", "Инвертировать выделение", "Снять выделение".

(* Выделить все *)
procedure TForm1.SelectAllClick(Sender: TObject);
var
  i: byte;
begin
   for i := 0 to 25 do
      if TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Enabled then
         TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Checked := true;
end;

(* Инвертировать выделение *)
procedure TForm1.InvertSelectClick(Sender: TObject);
var
  i: byte;
begin
   for i := 0 to 25 do
      if TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Enabled then
         TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Checked :=
            not TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Checked;
end;

(* Снять выделение *)
procedure TForm1.UnSelectAllClick(Sender: TObject);
var
  i: byte;
begin
   for i := 0 to 25 do
      TCheckBox( FindComponent( Format( 'Check%s', [Chr( i+65 )] ) ) ).Checked := false;
end;

Надеюсь, вы поняли принцип, и теперь у вас в арсенале станет на один прикол больше. Кроме того, этот принцип вы можете использовать и в своих программах, тем более что областей, где его можно применить, много. На этом сегодня все. Удачи в программировании.

.: Пример к данной статье :.


При использовании материала - ссылка на сайт обязательна