Хранитель экрана

   
На этом шаге мы рассмотрим создание хранителя экрана средствами OWL.

   
Студент 4 курса (2010-11 уч.год) Черемисов Сергей создал хранитель экрана средствами бибилиотеки OWL.

   
Чтобы запустить хранитель экрана, создайте проект из приведённых ниже файлов и откомпилируйте его. У полученного исполняемого
файла измените расширение на .scr и поместите его в папку windows\system32\. После этого хранитель экрана будет
доступен в стандартном окне настроек экрана Windows.

   
Приведём текст программы. Следуя традициям объектно-ориентированного программирования, описание классов поместим в файлы с
расширением .h, а реализацию - в .cpp.

   
Файл main.cpp:

#include "tapp.h"

int OwlMain(int, char *_argv[])
{
  return TApp().Run();
}

   
Описание класса TApp - файл tapp.h:

#ifndef _TAPP_h_
#define _TAPP_h_
#include <owl\applicat.h>
#include "twndw.h"
#include "tdlg.h"

class TApp: public TApplication
{
  public:
	 TApp() : TApplication() {}
	 void InitMainWindow();
  protected:
	 TWndw *SaverWnd;
	 TDialog *dialog;
	 BOOL IdleAction (long);
};
#endif

   
Реализация класса TApp - файл tapp.cpp:

#include "tapp.h"

void TApp::InitMainWindow()
{
  SaverWnd = NULL;
  char temp[80];
  if (_argv[1]!=NULL) // есди есть параметр, то
  strcpy(temp,_argv[1]); // копирование строки параметров
  else *temp='\0'; //иначе установить первым символом символ конца строки
  if ( !*temp || ((temp[0] == '/') || (temp[0] == '-')) &&
	  ( (temp[1] == 'c') || (temp[1] == 'C') ))
  //если параметр /c или нет параметра, то ...
  {
	 dialog = new TDlg(0, DIALOG_1);//создаём диалоговое окно настроек
	 TFrameWindow *wndw = new TFrameWindow (0, 0, dialog, TRUE);
	 //диалоговое окно должно иметь родительское окно
	 SetMainWindow(wndw); //устанавливаем главное окно приложения
  }
  else
  //если другой параметр (/s), то ...
  {
    SaverWnd = new TWndw(0, 0, 0); //создаём окно скринсейвера
    SetMainWindow(SaverWnd); //устанавливаем его в качестве главного окна приложения
  }
}

BOOL TApp::IdleAction(long) //функция, вызывающаяся при пустой очереди сообщений 
{
  if (SaverWnd) // если создано окно скринсейвера, 
		    //то выполнить действия по отрисовке изображения
  {
	 SaverWnd->DoSaver();
	 return TRUE;
  }
  else return FALSE;
}

   
Описание класса TDlg - файл tdlg.h:

#ifndef _TDLG_h_
#define _TDLG_h_
#include <owl\dialog.h>
#include <owl\combobox.h>
#include <owl\checkbox.h>
#include "saver.rc"

class TDlg : public  TDialog
{
  public:
	 TDlg (TWindow *parent, TResId resId);
  protected:
	 char LBStrg [3];
	 struct
	 {
		TListBoxData lbData;
		BOOL check;
	 } Buf;
	 TListBox *listbox;
	 TCheckBox *checkbox;
	 void SetupWindow();
	 void CmOk();
	DECLARE_RESPONSE_TABLE (TDlg);
};
#endif

   
Реализация класса TDlg - файл tdlg.cpp:

#include "tdlg.h"

DEFINE_RESPONSE_TABLE1 (TDlg, TDialog)
  EV_COMMAND (IDOK, CmOk),
END_RESPONSE_TABLE;

TDlg::TDlg (TWindow *parent, TResId resId):
		TDialog (parent, resId)
{
  listbox = new TListBox (this, IDC_LISTBOX1); //создать объект-список
  checkbox = new TCheckBox(this, IDC_CHECKBOX); //создать объект-флажок
  TransferBuffer = &Buf; //установить адрес буфера обмена для диалогового окна
}

//функция, вызывающаяся перед первым отображением окна на экране
void  TDlg::SetupWindow() 
{
  TDialog::SetupWindow(); 
  Buf.lbData.AddString("1"); // 
  Buf.lbData.AddString("2"); // 
  Buf.lbData.AddString("3"); //
  Buf.lbData.AddString("5"); //
  Buf.lbData.AddString("10");// установка значений списка
  Buf.lbData.AddString("15");//
  Buf.lbData.AddString("20");//
  Buf.lbData.AddString("40");//
  TransferData(tdSetData);  // перенести данные из буфера в диалоговое окно
  HKEY res; //дескриптор раздела реестра
  DWORD disp, sizestr=3, sizemode=1; 
  char mode=0; //режим скринсейвера по умолчанию
  if(RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\FigureScreenSaver\\", 0,
			  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
			  NULL, &res, &disp)==ERROR_SUCCESS)
  // создание/открытие раздела реестра windows 
{
	 if (disp==REG_CREATED_NEW_KEY) //если раздел был создан
	 // то создаём ключи и записываем в них значения по умолчанию
	 {
		RegSetValueEx(res,"Number",0, REG_SZ,(BYTE*)"20",3); 
		RegSetValueEx(res,"Mode",0, REG_BINARY, (BYTE*)&mode, 1);
		listbox->SetSelIndex(6); // по умолчанию выбрано значение "20" 
	 }
	 else //если раздел был открыт
	 {
		char numb[3]; 
		//читаем значение ключа с количеством отрисовываемых фигур
		RegQueryValueEx(res, "Number", 0, NULL, (BYTE*)numb, &sizestr);
		listbox->SetSelString(numb, -1);//устанавливаем выбранное значение
		// читаем значение ключа с режимом работы скринсейвера
		RegQueryValueEx(res, "Mode", 0, NULL, (BYTE*)&mode, &sizemode);
		// устанавливаем флажок в зависимости от выбранного режима
		checkbox->SetCheck(mode? BF_CHECKED: BF_UNCHECKED);
	 }
	 RegCloseKey(res); //завершаем работу с разделом
  }
  //если произошла ошибка при работе с реестром, то устанавливаем выбор по умолчанию
  else listbox->SetSelIndex(6); 
}

void TDlg::CmOk()
{
  TransferData(tdGetData); //переносим данные из диалога в буфер
  HKEY res;
  Buf.lbData.GetSelString(LBStrg, sizeof(LBStrg));//получаем выбранную строку
  char mode=Buf.check? 1: 0;//устанавливаем нужный режим
  //создаём/открываем раздел реестра
  if(RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\FigureScreenSaver\\", 0,
			  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
			  NULL, &res, NULL)==ERROR_SUCCESS)
  //если раздел успешно создан/открыт, то записываем выбранные значения в реестр
  {
	RegSetValueEx(res,"Number",0,REG_SZ, (BYTE*)LBStrg, strlen(LBStrg)+1);
	RegSetValueEx(res,"Mode",0, REG_BINARY, (BYTE*)&mode, 1);
	RegCloseKey(res); //завершаем работу с разделом
  }
  else MessageBox("Невозможно сохранить настройки", "Внимание", MB_OK | MB_ICONHAND);
  TDialog::CmOk();
}

   
Описание класса TWndw - файл twndw.h:

#ifndef _TWNDW_h_
#define _TWNDW_h_
#include <owl\framewin.h>
#include "figure.h"

typedef Figure *Figure_p; // тип-указатель на объект класса Figure

class TWndw: public TFrameWindow
{
  public:
	 TWndw(TWindow *parent, const char far *title, TWindow *client);
	 ~TWndw ();
	 void DoSaver();
  protected:
	 TPoint mouseXY; 
	 Figure_p *fff; //указатель на массив указателей на фигуры
	 int Num; // количество отрисовываемых фигур
	 char mode; //режим работы скринсейвера
	 void GetWindowClass (WNDCLASS &wndClass);
	 void EvLButtonDown (UINT, TPoint&);
	 void EvMButtonDown (UINT, TPoint&);
	 void EvRButtonDown (UINT, TPoint&);
	 void EvMouseMove (UINT, TPoint &point);
	 void EvSysCommand (UINT, TPoint&);
	 void EvActivate (UINT, BOOL, HWND);
	 void EvActivateApp (BOOL, HTASK);
	 void EvSysKeyDown (UINT, UINT, UINT);
	 void EvKeyDown (UINT, UINT, UINT);
	 char far *GetClassName();
	DECLARE_RESPONSE_TABLE (TWndw);
};
#endif

   
Реализация класса TWndw - файл twndw.cpp:

#include "twndw.h"

DEFINE_RESPONSE_TABLE1(TWndw,TFrameWindow)
	 EV_WM_LBUTTONDOWN,
	 EV_WM_MBUTTONDOWN,
	 EV_WM_RBUTTONDOWN,
	 EV_WM_MOUSEMOVE,
	 EV_WM_SYSCOMMAND,
	 EV_WM_ACTIVATE,
	 EV_WM_ACTIVATEAPP,
	 EV_WM_SYSKEYDOWN,
	 EV_WM_KEYDOWN,
END_RESPONSE_TABLE;

TWndw::TWndw (TWindow *parent, const char far *title,
  TWindow *client):TFrameWindow(parent, title, client)
{
  HKEY res;
  //чтение настроек скринсейвера из реестра или установка настроек по умолчанию
  if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\FigureScreenSaver\\", 0,
					  KEY_QUERY_VALUE,&res)==ERROR_SUCCESS)
  {
    char numb[3];
    DWORD sizestr=3, sizemode=1;
    if (RegQueryValueEx(res, "Number", 0, NULL, (BYTE*)numb, &sizestr)==ERROR_SUCCESS)
       Num=atoi(numb);
    else Num=20;
    if (RegQueryValueEx(res, "Mode", 0, NULL, (BYTE*)&mode, &sizemode)!=ERROR_SUCCESS)
       mode=0;
    RegCloseKey(res);
  }
  else Num=20;
  randomize();
  GetCursorPos(mouseXY);//запоминаем положение курсора мыши
  ShowCursor(FALSE);//скрываем курсор
  Attr.Style = WS_POPUP;//стиль окна
  Attr.X = 0;
  Attr.Y = 0;
  Attr.W = GetSystemMetrics (SM_CXSCREEN);//
  Attr.H = GetSystemMetrics (SM_CYSCREEN);// размер окна на весь экран
  fff=new Figure_p[Num]; // выделяем память под массив указателей на фигуры
  // создаём фигуры и помещаем их адреса в массив
  for(int i=0; i<Num;i++) fff[i]=new Figure(Attr.W/2, Attr.H/2, TColor(random(256),
				random(256),random(256)), 180-random(360));
}

TWndw::~TWndw ()
{
  ShowCursor(TRUE); //показываем курсор
  for(int i=0; i<Num;i++) delete fff[i]; //освобождаем память из-под фигур
  delete [] fff; // освобождаем память из-под массива
}

void TWndw::GetWindowClass (WNDCLASS &wndClass)
//функция, заполняющая структуру оконного класса
{
  TFrameWindow::GetWindowClass (wndClass);
  wndClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
}

char far *TWndw::GetClassName()
//функция, возвращающая имя класса окна
{
  return   "WindowsScreenSaverClass";
}

void TWndw::EvMouseMove(UINT, TPoint& point)
//функция, вызывающаяся при движении мыши
{
  //если мышь была сдвинута, то поместить в очередь сообщений WM_CLOSE
  if (point != mouseXY) PostMessage(WM_CLOSE);
}

void TWndw::EvLButtonDown(UINT, TPoint&)
//функция, вызывающаяся при нажатии левой кнопки мыши
{
  PostMessage(WM_CLOSE);
}

void TWndw::EvMButtonDown(UINT, TPoint&)
//функция, вызывающаяся при нажатии средней кнопки мыши
{
  PostMessage(WM_CLOSE);
}

void TWndw::EvRButtonDown (UINT, TPoint&)
//функция, вызывающаяся при нажатии правой кнопки мыши
{
  PostMessage(WM_CLOSE);
}

void TWndw::EvActivate (UINT active, BOOL, HWND)
//функция, вызывающаяся при активации/деактивации окна
{
  if (!active) PostMessage (WM_CLOSE);
}

void TWndw::EvActivateApp (BOOL active, HTASK)
//функция, вызывающаяся при активации/деактивации окон различных приложений
{
  if (!active) PostMessage (WM_CLOSE);
}

void TWndw::EvKeyDown(UINT, UINT, UINT)
{
  PostMessage(WM_CLOSE);
}

void TWndw::EvSysKeyDown(UINT, UINT, UINT) 
//функция, вызывающаяся при нажатии системной клавиши
{
  PostMessage(WM_CLOSE);
}

void TWndw::EvSysCommand(UINT cmdType, TPoint&)
//проверка на запуск второго скринсейвера
{
  if ((cmdType & 0xFFF0) != SC_SCREENSAVE) DefaultProcessing();
}

void TWndw::DoSaver()
//действия по отрисовке фигур
{
	TMemoryDC ddb; //создать контекст в памяти
	TClientDC ddd(HWindow); //создать контекст для окна скринсейвера
	//получить прямоугольник клиентской области окна
	TRect ss = ddd.GetClipBox(); 
	TSize sz = ss.Size(); // получить его размеры 
	// создать растр для контекста в памяти,
	//совместимый с контекстом главного окна
	TBitmap bitmap(ddd, sz.cx, sz.cy, FALSE);
	ddb.SelectObject(bitmap); //выбрать созданный растр для контекста ddb
	//в зависимости от режима перенести изображение с экрана в память
	if (mode) ddb.BitBlt(0, 0,  sz.cx, sz.cy,ddd, 0, 0);
	for(int i=0; i<Num;i++) fff[i]->Saver(ddb); //отрисовать все фигуры
	// перенести изображение из памяти на экран 
	ddd.BitBlt(0, 0,  sz.cx, sz.cy,ddb, 0, 0);
}

   
Описание класса Figure - файл figure.h:

#ifndef _FIGURE_h_
#define _FIGURE_h_
#include <owl\dc.h>
#include <math.h>
#include <time.h>

class Figure
{
  private:
	 float a, b, c, //углы поворота фигуры
	 gx, //размер
	 xc, yc, //координаты центра
	 da, db, dc; //приращения углов поворота
	 TColor col; //цвет
	 int fi, //направление движение фигуры
	 mx, my; // горизонтальное/вертикальное отражение направления движения
	 void Draw(int, float ,float, float, float, float, TDC &);
	 void Drawer(int, float, float, TDC& );
  public:
	 void Saver(TDC &);
	 Figure(float, float, TColor, int );
};
#endif

   
Реализация класса Figure - файл figure.cpp:

#define PI 3.14159
#include <time.h>
#include "figure.h"
#define randangle 0.05-float(random(1000))/float(10000);

Figure::Figure(float x, float y, TColor cc, int f)
{
  //установка начальных значений параметров фигуры
  xc=x;
  yc=y;
  b=c=0;
  a=3*PI;
  da=db=dc=0.05;
  col=cc;
  fi=f;
  mx=my=1;
  gx=random(15)+5;
}

void Figure::Draw(int i, float x,float y,float z, float x0, float y0, TDC &ddb)
//функция отрисовки очередной линии фигуры
{
  float  y1, z1;
  //преобразование координат производится матрицей поворота
  y1=cos(c)*(x*sin(a)+y*cos(a))-sin(c)*(sin(b)*(x*cos(a)-y*sin(a))+z*cos(b));
  z1=sin(c)*(x*sin(a)+y*cos(a))+cos(c)*(sin(b)*(x*cos(a)-y*sin(a))+z*cos(b));
  if ((y==-3 && i) || (x==-3 && !i)) ddb.MoveTo(x0+int(y1*gx), y0-int(z1*gx));
  else ddb.LineTo(x0+int(y1*gx), y0-int(z1*gx));
}

void Figure::Drawer(int i, float x0, float y0, TDC& ddb)
//функция отрисовки полуфигуры
{
	float x, y, z;
	x=-3;
	//рисование "продольных" линий
	do
	{
	  y=-3;
	  do
	  {
		 z=float(i)*sqrt(18-x*x-y*y); //Уравнение полусферы
		 Draw(1, x, y, z, x0, y0, ddb);
		 y++;
	  } while (y<=3);
	  x++;
	}
	while (x<=3);
	y=-3;
	//рисование "поперечных" линий
	do
	{
	  x=-3;
	  do
	  {
		 z=float(i)*sqrt(18-x*x-y*y);
		 Draw(0, x, y, z, x0, y0, ddb);
		 x++;
	  } while (x<=3);
	  y++;
	}
	while (y<=3);
}

void Figure::Saver(TDC &ddb)
{
	TPen pen(col, 1, PS_SOLID);//создать перо нужного цвета
	ddb.SelectObject(pen);//выбрать перо

	Drawer(1, xc, yc, ddb); //отрисовать верхнюю половину фигуры
	Drawer(-1, xc, yc, ddb);//отрисовать нижнюю половин

	TRect ss = ddb.GetClipBox(); //получить прямоугольник клиентской области окна
	TSize sz = ss.Size(); // получить его размеры

	randomize();

	if(a<=2*PI) a+=da; else a=0; //
	if(b<=2*PI) b+=db; else b=0; // "поворачиваем" фигуру
	if(c<=2*PI) c+=dc; else c=0; //

	xc+=float(mx)*6*cos(fi*PI/180); // "передвигаем" фигуру
	yc+=float(my)*6*sin(fi*PI/180); // 

	if (fabs(xc)<gx*5 || fabs(xc-sz.cx)<gx*5) 
	// если фигура достигла левого/правого края экрана
	{
	  mx*=-1; // отражаем движение по горизонтали
	  da=randangle; //
	  db=randangle; // устанавливаем случайные приращение углов
	  dc=randangle; //
	}
	else if (fabs(yc)<gx*5 || fabs(yc-sz.cy)<gx*5)
	// если фигура достигла верхнего/нижнего края экрана
	{
	  my*=-1; // отражаем движение по вертикали
	  da=randangle; //
	  db=randangle; // устанавливаем случайные приращение углов
	  dc=randangle; //
	}
}

   
Файл ресурсов saver.rc:

#ifndef WORKSHOP_INVOKED
#include "windows.h"
#endif

#define  DIALOG_1        200
#define IDC_LISTBOX1     102
#define IDC_CHECKBOX     103

#ifdef RC_INVOKED
DIALOG_1 DIALOG 101, 83, 109, 113
STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION
CAPTION "Screensaver FIGURES"
LANGUAGE LANG_RUSSIAN, 0
{
 PUSHBUTTON "OK", IDOK, 10, 90, 40, 14, WS_TABSTOP
 PUSHBUTTON "Cancel", IDCANCEL, 60, 90, 39, 14
 LTEXT "Number of figures", -1, 20, 9, 70, 10
 LISTBOX IDC_LISTBOX1, 20, 20, 70, 40, LBS_NOTIFY | WS_BORDER | 
         WS_BORDER | WS_VSCROLL
 AUTOCHECKBOX """Psyho"" mode", IDC_CHECKBOX, 20, 71, 71, 10
}
#endif

Текст этого приложения можно взять здесь.

   
При вызове настроек скринсейвера появляется окно:


Рис.1. Окно настроек хранителя экрана
в котором можно выбрать количество рисуемых фигур и режим их рисования.

   
Следует обратить внимание на WinAPI-функции работы с реестром.

  LONG RegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions,
                REGSAM samDesired, PHKEY phkResult) 

   
Функция открывает раздел реестра. Ее параметры:

  • hKey - описатель открываемого раздела, который может быть получен функциями
    RegCreateKeyEx и RegOpenKey. Действуют стандартные описатели, перечисленные выше.
  • lpSubKey - указатель на строку, завершающуюся нулевым байтом, которая содержит имя открываемого раздела.
    Этот раздел должен быть подразделом, идентифицируемого описателем раздела. Если этот параметр NULL, то функция
    вернет описатель самого раздела, т. е. раздела, идентифицируемого описателем.
  • ulOptions - зарезервировано (0).
  • samDesired - определяет права доступа (действия, которые будет проделывать с разделом программист). Как уже
    упоминалось, раздел реестра является системным объектом, а следовательно он имеет дескриптор защиты, именно в нем
    перечисляются права пользователей на объект. Определены следующие стандартные макросы:

    • KEY_ALL_ACCESS - разрешаются любые действия над разделом;
    • KEY_ENUMERATE_SUB_KEYS - разрешается перечисление подразделов данного раздела;
    • KEY_READ - разрешается чтение раздела;
    • KEY_SET_VALUE - разрешается создавать, удалять параметр или устанавливать его значение;
    • KEY_QUERY_VALUE - разрешается запрос параметра раздела.
  • phkResult - указатель на переменную, получающую описатель открытого раздела.

   
Если открытие произошло успешно, функция вернет ERROR_SUCCESS, в противном случае вернет ненулевой код ошибки,
определенный в Winerror.h.

  LONG RegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved,
      LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired,
      LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,
      LPDWORD lpdwDisposition);

   
Функция создает раздел реестра. Если раздел уже существует, функция открывает его. Имена разделов не чувствительны к регистру.

  • hKey - описатель открываемого раздела.
  • lpSubKey - указатель на строку, завершающуюся нулевым байтом, которая содержит имя создаваемого или
    открываемого раздела.
  • Reserved - зарезервировано (0).
  • lpClass - указатель на строку, завершающуюся нулевым байтом, которая содержит класс этого раздела. Может быть
    проигнорирован и равен NULL. Используется для подключения к удаленному реестру.
  • dwOptions - параметр может принимать следующие значения:
    • REG_OPTION_BACKUP_RESTORE - если флаг установлен, функция игнорирует параметр samDesired и
      пытается открыть раздел с правами, для резервного копирования и восстановления раздела. Если поток вызывает функцию, обладая
      привилегией SE_BACKUP_NAME, то раздел открывается с правами доступа ACCESS_SYSTEM_SECURITY и
      KEY_READ. Если вызывающий поток обладает привилегией SE_RESTORE_NAME, то раздел открывается с
      правами доступа ACCESS_SYSTEM_SECURITY и KEY_WRITE. Если поток обладает обоими привилегиями,
      то раздел открывается с комбинированными правами доступа;
    • REG_OPTION_VOLATILE - раздел, созданный с помощью этого флага, изменчив. При этом информация сохраняется в
      памяти и не сохраняется, когда соответствующий улей выгружается. Для HKEY_LOCAL_MACHINE это происходит, когда
      компьютер выключается или перезагружается. Для разделов реестра, загруженных функцией RegLoadKey, это происходит,
      когда выполнена функция RegUnLoadKey. Функция RegSaveKey не сохраняет изменчивые разделы реестра.
      Этот флаг игнорируется, если раздел уже существует;
    • REG_OPTION_NON_VOLATILE - раздел, созданный с помощью этого флага, не изменяем. При этом информация
      записывается в файл реестра. Функция RegSaveKey сохраняет неизменчивые разделы.
  • samDesired - определяет права доступа для создаваемого раздела.
  • lpSecurityAttributes - указатель на структуру SECURITY_ATTRIBUTES. Если параметр равен NULL, то
    описатель раздела не наследуется порожденным (дочерним) процессом. В эту структуру входит дескриптор защиты раздела. Если
    параметр равен NULL, раздел получает дескриптор защиты по умолчанию. Список управления доступом (ACL) в
    заданном по умолчанию дескрипторе защиты для раздела, наследуются от родительского раздела.
  • phkResult - указатель на переменную, получающую описатель открытого или созданного раздела.
  • lpdwDisposition - указатель на переменную, в которую записывается одно из следующих значений.
    • REG_CREATED_NEW_KEY - раздел не существует и будет создан;
    • REG_OPENED_EXISTING_KEY - раздел существует.

    Если параметр равен NULL, то никакая информация не возвращается.

   
Если открытие произошло успешно, функция вернет ERROR_SUCCESS, в противном случае вернет ненулевой код ошибки,
определенный в Winerror.h.

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

  LONG RegCloseKey(HKEY hKey); 

hKey - описатель открытого раздела, который подлежит закрытию.

   
Если описатель успешно освобожден, функция возвращает ERROR_SUCCESS, в противном случае вернет ненулевой код
ошибки, определенный в Winerror.h.

  LONG RegQueryValueEx(HKEY hKey, LPCTSTR lpValueName, 
    LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) 

   
Функция возвращает информацию о параметре раздела и значение этого параметра.

  • hKey - описатель открытого раздела. Раздел должен быть открыт с правами KEY_QUERY_VALUE.
  • lpValueName - указатель на С-строку, содержащую название параметра, о котором получается информация. Если
    параметр - NULL или пустая строка, то возвращается информация о параметре по умолчанию.
  • lpReserved - зарезервирован (NULL).
  • lpType - указатель на переменную, которая получает тип данных, сохраненных в параметре. Если равен NULL,
    то, соответственно, информация не возвращается.
  • lpData - указатель на массив, получающий данные параметра. Если параметр - NULL, то данные не возвращаются.
    Если данные - это строка, то функция проверяет наличие нулевого символа.
  • lpcbData - указатель на переменную, которая определяет размер буфера, принимающего данные из параметра, в байтах.
    После того, как функция вернет значение, эта переменная будет содержать размер данных, скопированных в буфер. Если данные
    носят текстовый характер (REG_xxx_SZ), то также включается и нулевой символ (нулевые символы для REG_MULTI_SZ).
    Если размер буфера недостаточен для сохранения данных, то функция вернет ERROR_MORE_DATA и сохранит требуемый
    размер буфера в переменную, на которую указывает этот параметр.

   
Если lpData - NULL, а параметр
lpcbData не нулевой, функция возвращает ERROR_SUCCESS и сохраняет размер данных в переменной,
на которую указывает lpcbData.

   
Если функция выполнена успешно, возвращается ERROR_SUCCESS, в противном случае возвращается ненулевой код
ошибки, определенный в Winerror.h.

  LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, 
    DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData) 

   
Функция устанавливает значение параметра.

  • hKey - описатель открытого раздела. Раздел должен быть открыт с правами KEY_SET_VALUE.
  • lpValueName - указатель на строку, которая содержит название параметра, значение которого нужно установить. Если
    параметра с таким именем не существует, функция создаст его. Если параметр равен NULL, или пустой строке, то
    устанавливается значение параметра по умолчанию. В Windows Me/98/95 каждый раздел имеет параметр по умолчанию,
    который первоначально не содержит данных. В Windows 95 по умолчанию тип этого параметра - REG_SZ.
  • Reserved - зарезервировано (NULL).
  • dwType - тип данных параметра.
  • lpData - указатель на буфер, содержащий данные, которые должны быть сохранены в соответствующем параметре. Для
    строк, таких как REG_SZ, строка должна заканчиваться нулевым символом. Для типа REG_MULTI_SZ строка должна
    заканчиваться двумя нулевыми символами.
  • cbData - hазмер буфера lpData в байтах. Если данные имеют тип REG_SZ, REG_MULTI_SZ или
    REG_EXPAND_SZ, то параметр должен учитывать нулевой или нулевые символы.

   
Если функция выполнена успешно, возвращается ERROR_SUCCESS, в противном случае возвращается ненулевой код
ошибки, определенный в Winerror.h.

   
На следующем шаге мы рассмотрим создание приложения, изменяющего параметры шрифта.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий