Обзоры игр, статьи, программы, обои, игры, общение...

  

Программирование для всех

.: НАВИГАЦИЯ 3D

--- 3D Touch ---

 

.: СЧЁТЧИКИ

Рейтинг@Mail.ru

 

.: БАННЕРЫ

Rambler's Top100

 

.: РЕКЛАМА

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

 

.: ПРИКОЛЬНОЕ ФОТО

C++ & WinAPI: Виртуальные девайсы

Здравствуйте, уважаемые господа-программеры! Перед вами очередная статья из этого цикла. Сегодня мы поговорим о стандартных API-функциях для создания и управления виртуальными девайсами. В частности QueryDosDevice() и DefineDosDevice(). А так же напишем программу-пример, которая будет реализовывать возможности этих функций. Описание функций:

BOOL DefineDosDevice(
DWORD dwFlags, // параметры
LPCTSTR lpDeviceName, // имя устройства
LPCTSTR lpTargetPath // путь к каталогу
);

Описание:
Предназначена для создания, изменения и удаления MS-DOS девайсов. Вообще-то эта функция не предназначена для работы с настоящими девайсами, она может управлять лишь символическими ссылками (symbolic links) на определенный каталог на локальном
диске или на сетевой ресурс.

Совместимость: Windows NT/2000/XP
Библиотека: Kernel32.lib (Kernel32.dll)

DWORD QueryDosDevice(
LPCTSTR lpDeviceName, // имя устройства MS-DOS
LPTSTR lpTargetPath, // буффер результатов запроса
DWORD ucchMax // максимальный размер буффера
);

Описание:
Функция возвращает путь к MS-DOS девайсу.
Совместимость: Windows 95/98/Me/NT/2000/XP
Библиотека: Kernel32.lib (Kernel32.dll)

Разберем по-подробнее функцию DefineDosDevice():

Параметр dwFlags может принимать следующие значения (взято из MSDN):

¦---------------------------¦------------¦---------------------------------------¦
¦ Константа ¦ Значение ¦ Описание¦
¦---------------------------¦------------¦---------------------------------------¦
¦ DDD_RAW_TARGET_PATH ¦ 0x00000001 ¦ If this value is specified, the ¦
¦ ¦ ¦ function does not convert the ¦
¦ ¦ ¦ lpTargetPath string from an MS-DOS ¦
¦ ¦ ¦ path to a path, but takes it as is. ¦
¦---------------------------¦------------¦---------------------------------------¦
¦ DDD_REMOVE_DEFINITION ¦ 0x00000002 ¦ If this value is specified, the ¦
¦ ¦ ¦ function removes the specified ¦
¦ ¦ ¦ definition for the specified device. ¦
¦ ¦ ¦ To determine which definition to ¦
¦ ¦ ¦ remove, the function walks the list ¦
¦ ¦ ¦ of mappings for the device, looking ¦
¦ ¦ ¦ for a match of lpTargetPath against ¦
¦ ¦ ¦ a prefix of each mapping associated ¦

¦ ¦ ¦ with this device. The first mapping ¦
¦ ¦ ¦ that matches is the one removed, ¦
¦ ¦ ¦ and then the function returns. ¦
¦ ¦ ¦ ¦
¦ ¦ ¦ If lpTargetPath is NULL or a pointer ¦
¦ ¦ ¦ to a NULL string, the function will ¦
¦ ¦ ¦ remove the first mapping associated ¦
¦ ¦ ¦ with the device and pop the most ¦
¦ ¦ ¦ recent one pushed. If there is ¦
¦ ¦ ¦ nothing left to pop, the device name ¦
¦ ¦ ¦ will be removed. ¦
¦ ¦ ¦ ¦
¦ ¦ ¦ If this value is NOT specified, the ¦
¦ ¦ ¦ string pointed to bythe lpTargetPath ¦
¦ ¦ ¦ parameter will become the new mapping ¦
¦ ¦ ¦ for this device. ¦
¦---------------------------¦------------¦---------------------------------------¦
¦ DDD_EXACT_MATCH_ON_REMOVE ¦ 0x00000004 ¦ If this value is specified along with ¦
¦ ¦ ¦ DDD_REMOVE_DEFINITION, the function ¦
¦ ¦ ¦ will use an exact match to determine ¦
¦ ¦ ¦ which mapping to remove. Use this ¦
¦ ¦ ¦ value to insure that you do not ¦
¦ ¦ ¦ delete something that you did not ¦
¦ ¦ ¦ define. ¦
¦---------------------------¦------------¦---------------------------------------¦

Для тех, кто в танке, поясню: DDD_RAW_TARGET_PATH - принять путь к устройству без конвертации, DDD_REMOVE_DEFINITION - удаление устройства, DDD_EXACT_MATCH_ON_REMOVE - используется вместе с DDD_REMOVE_DEFINITION, не позволит удалить ненароком чего-либо лишнего ;) Остальные параметры функции, я думаю, не нуждаются в пояснении.

А c QueryDosDevice() еще проще: в lpDeviceName задается имя девайса, в lpTargetPath - адрес буфера в памяти, а в ucchMax - максимальный размер этого буфера.

Ну а сейчас, как я уже говорил, перейдем непосредственно к практике. Для примера давайте закодим простую программу для управления виртуальными девайсами. Основные возможности проги: создать новый девайс, удалить существующий девайс, получить путь к девайсу. Для большего удобства наша программа должна обладать GUI интерфейсом. Давайте не будем писать его на 'чистом' API, т.к. при этом нам придется собственноручно создавать и описывать каждый элемент в окне. Согласитесь, это слишком долго и не удобно. Гораздо проще использовать ресурсы. Для этого при помощи того же Visual C++ 6 мы создадим диалог, набросаем на него необходимых нам контролов, а затем в нашей программе опишем функцию обработки сообщений. Итак, приступим...

Запускайте свой Visual C++ и создавайте новый пустой win32 проект (File->New->Project->Win32 Application->An empty project). Теперь необходимо добавить в него пустой cpp файл и файл ресурсов. Я не буду заострять на этом особое внимание, т.к. вы должны уметь делать это самостоятельно (иначе какой же вы программист? :). Далее создаем новый диалог и кидаем на него некоторые контролы. Вот их список:

Group Box (5 шт.)
Static Text (3 шт.)
Edit Box (5 шт.)

У вас должна получиться примерно такая картина:

<img src="dialog.jpg">

Поясню назначение некоторых элементов:

Группа Control Center, Поле Create, EditBox 1 - символ диска (c,d,e....)
Группа Control Center, Поле Create, EditBox 2 - Путь к диску
Группа Control Center, Поле Create, Button - создание нового диска
Группа Control Center, Поле Remove, EditBox - символ диска (c,d,e....)
Группа Control Center, Поле Remove, Button - удаление диска
Группа Control Center, Поле Get path, EditBox - символ диска (c,d,e....)
Группа Control Center, Поле Get path, Button - получение пути к диску
Группа Messages, EditBox - сообщения программы


А теперь перейдем к кодингу...

Для начала подключим необходимые заголовочные файлы:

#include <windows.h>
#include <CommCtrl.h>
#include <stdio.h>
#include "resource.h"

и объявим некоторые переменные:

#define IDM_ABOUT 0
HMENU hmenuChart; //пункт меню
HMENU hmain; //главное меню диалога

После этого необходимо подключить к проекту следующие библиотеки: msvcrt.lib kernel32.lib user32.lib comctl32.lib. Также нужно написать функцию вывода сообщений программы в IDC_EDIT4. Вот ее код:

void __stdcall WriteLog(HWND hwnd, char* str)
{
   EnableWindow(GetDlgItem(hwnd,IDC_EDIT4),TRUE);
   for(unsigned int i = 0; i < strlen(str); i++) SendDlgItemMessage((HWND)hwnd,IDC_EDIT4,WM_CHAR,str[i],0);
   //посимвольно заполняем IDC_EDIT4
   EnableWindow(GetDlgItem(hwnd,IDC_EDIT4),FALSE);
}

В функции WinMain мы инициализируем контролы

InitCommonControls();

И создаем наш диалог

DialogBox(hinst,MAKEINTRESOURCE(IDD_DIALOG1),NULL,Dlg_Proc);

Здесь предполагается, что IDD_DIALOG1 - это название диалога, а Dlg_Proc - функция обработки сообщений. Т.к. этой функции у нас еще нет, то нам нужно будет ее написать. В целях экономии места, я приведу только ее основные параметры.

Сама функция имеет следующий вид:

int __stdcall Dlg_Proc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam), где

hwnd - хандл окна, wMsg - сообщение, wParam и lParam параметры сообщения.

Объявление переменных:

char dl, drv[255];
OSVERSIONINFO os;
RECT r,r2;
char* path, *path2, *temp;

Обработка сообщения WM_INITDIALOG:

hmenuChart = CreatePopupMenu(); //создаем новый пункт меню
hmain = CreateMenu(); //и само меню
AppendMenu(hmenuChart, MF_STRING, IDM_ABOUT, "About");
AppendMenu(hmain, MF_STRING | MF_POPUP, (UINT_PTR)hmenuChart, "Help"); //добавим к нему этот пункт в раздел Help
SetMenu(hwnd, hmain); //добавим меню к диалогу
EnableWindow(GetDlgItem(hwnd,IDC_EDIT4),FALSE); //"выключаем" IDC_EDIT4 (сообщения программы)
GetWindowRect(GetDesktopWindow(),&r);
GetWindowRect(hwnd,&r2);
SetWindowPos(hwnd, NULL, r.right/2-373/2, r.bottom/2-420/2, 373, 420, 0); //window pos = desktop center

Обработка сообщения WM_CLOSE:

EndDialog(hwnd,1);

Далее у нас идет обработчик команд. В нем я реализовал все основные функции программы, т.ч. вникай в комментарии к коду... Обработка IDM_ABOUT:

MessageBox(hwnd, "VDD2 - Copyright (C) NeTxXx. <develop@list.ru>","About",MB_OK+MB_ICONINFORMATION); //о программе

Обработка IDC_BUTTON3: 

//получить путь к девайсу 
GetDlgItemText(hwnd,IDC_EDIT3,drv,255); //получаем строку из IDC_EDIT3
dl = drv[0]; //в dl запишем I символ drv
temp = (char*)malloc((size_t)255); //выделяем память для temp
memset(temp,0,(size_t)255); //заполняем temp нулями
path = (char*)malloc((size_t)255); //выделяем память для path
memset(path,0,(size_t)255); //заполняем path нулями
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); //инициализируем структуру OSVERSIONINFO
if (GetVersionEx(&os)==0) //получаем системную информацию
{
WriteLog(hwnd,"ERROR getting windows version!");
return 1;
}
if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) //если платформа = WinNT
{
char buff2[2];
buff2[0] = dl;
buff2[1] = ':';
buff2[2] = '0';
QueryDosDevice(buff2,path,255); //получаем путь к девайсу
sprintf(temp, "Local path to virtual drive %c:%s", dl, path);
WriteLog(hwnd, temp);
} else
{
WriteLog(hwnd, "VDD2 works only on WIN NT platform!"); //выходим из функции если платформа != WinNT
return 1;
}
//освобождаем память
free(temp);
free(path);
Обработка IDC_BUTTON2: //удаление девайса
GetDlgItemText(hwnd,IDC_EDIT2,drv,255); //получаем ->
dl = drv[0]; //-> символ девайса
//выделение памяти под переменные
temp = (char*)malloc((size_t)255);
memset(temp,0,(size_t)255);
path = (char*)malloc((size_t)255);
memset(path,0,(size_t)255);
path2 = (char*)malloc((size_t)255);
memset(path2,0,(size_t)255);
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&os)==0) //получаем системную информацию
{
WriteLog(hwnd,"ERROR getting windows version!");
return 1;
}
if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) //если платформа = WinNT
{
char buff2[2];
buff2[0] = dl;
buff2[1] = ':';
buff2[2] = '0';
QueryDosDevice(buff2,path,256); //получаем путь к девайсу
if (strchr(path,'?')!=NULL) //удаляем лишние символы ("??")
{
path += 4;
strncpy(path2,path,(int)strlen(path));
} else {
strncpy(path2,path,(int)strlen(path));
}
if (path2[strlen(path2)-1] != '\')
strcat(path2,"\");
if (!DefineDosDevice(DDD_REMOVE_DEFINITION,buff2,path2)) //удаляем девайс
{
WriteLog(hwnd,"ERROR removing device!");
return 1;
}
sprintf(temp, "Virtual drive %c was successfully removed.", dl);
WriteLog(hwnd, temp);
} else
{
WriteLog(hwnd, "VDD2 works only on WIN NT platform!"); //выходим из функции если платформа != WinNT
return 1;
}
//освобождаем память
free(temp);
free(path);

Обработка IDC_BUTTON2: 

//создание девайса
GetDlgItemText(hwnd,IDC_EDIT1,drv,255); //получаем ->
dl = drv[0]; //-> символ девайса
//выделение памяти под переменные
path = (char*)malloc((size_t)255);
memset(path,0,(size_t)255);
temp = (char*)malloc((size_t)255);
memset(temp,0,(size_t)255);
GetDlgItemText(hwnd,IDC_EDIT5,path,255);
if (path[strlen(path)-1] != '\')
strcat(path,"\");
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&os)==0) //получаем системную информацию
{
WriteLog(hwnd,"ERROR getting windows version!");
return 1;
}
if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) //если платформа = WinNT
{
char buff[2];
buff[0] = dl;
buff[1] = ':';
buff[2] = '0';
if (!DefineDosDevice(0,buff,path)) //создаем новый девайс
{
WriteLog(hwnd,"ERROR defining device!");
return 1;
}
//обрадуем юзера сообщением :)
sprintf(temp, "Virtual drive %c was successfully created.", dl);
WriteLog(hwnd, temp);
sprintf(temp, "Local path to virtual drive %c: %s", dl, path);
WriteLog(hwnd, temp);
sprintf(temp, "Enjoy!");
WriteLog(hwnd, temp);
} else
{
WriteLog(hwnd, "VDD2 works only on WIN NT platform!"); //выходим из функции если платформа != WinNT
return 1;
}
free(temp);
free(path);

Вот пожалуй и все. Осталось только скомпилировать и запустить программу. После компиляции (естественно успешной), запустите программу и проверьте, создаются ли новые девайсы. Если да - все OK, а если же нет - убедитесь что у вас стоит WinNT и проверьте свой код на наличие ошибок. В итоге у нас получилась удобная и в то же время простая утилита для управления виртуальными девайсами. Но к сожалению у нее есть один большой недостаток: функционирование ТОЛЬКО на NT планформах. Так что счастливым обладателям Win9x придется довольствоваться только локальными дисками на компьютере, либо ждать следующую статью из этого цикла. В ней я постараюсь подробно изложить все аспекты работы с альтернативами рассмотренных нами функций в Win9x системах, а так же убрать с нашей утилиты таргет WinNT only ;)
Продолжение следует....

Автор: NeTxXx Copyright (C) 2003-2004 e-mail: develop@list.ru 

Размещено: 5.06.2005

 

 

 

 Worlds3D by Nicolaev Oleg Copyright © 2005

© 2002-2005 , Nic Soft Arts All Rights Reserved

© 2005 , Dream Software All Rights Reserved

Дизайн: Студия web-mast www.igropad.narod.ru

Hosted by uCoz