Win32 API 注冊表類的編制以及使用
發(fā)表時間:2024-06-11 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]一、問題的提出Windows 已由原來的16位 windows 3.x 升級為現(xiàn)今我們使用的32位windows 95/97/98 以其 Windows NT,用戶不僅在使用上應逐步適應,對于程序開發(fā)人員來說在編程技術(shù)上也應緊跟操作系統(tǒng)的技術(shù)發(fā)展,就如同 在 Linux 操作系統(tǒng)下, X-Wind...
一、問題的提出
Windows 已由原來的16位 windows 3.x 升級為現(xiàn)今我們使用的32位windows 95/97/98 以其 Windows NT,用戶不僅在使用上應逐步適應,對于程序開發(fā)人員來說在編程技術(shù)上也應緊跟操作系統(tǒng)的技術(shù)發(fā)展,就如同 在 Linux 操作系統(tǒng)下, X-Window 編程就顯得很重要一樣。作為一個完整成熟的 Windows 程序,需要保存程序所有的環(huán)境變量和私有信息。諸如用戶的偏好,文件裝入的列表、退出時用戶使用的窗口位置 .存盤歷史紀錄等。過去在 windows 3.x時代 ,常用 Win16函數(shù) Get/RegWrite ProfileString 將有關(guān)程序的信息寫入 *.ini 文件,但現(xiàn)在該項技術(shù)由 Win32注冊表所替代。
可以這樣說,注冊表是當今32位 Windows 操作系統(tǒng)的靈魂,一切信息都在其中,也就是為什么Windows98在Windows95的基礎(chǔ)上升級可以不重裝軟件等等的如此方便的應用,其原理就是根據(jù)了原注冊表中的信息來完成各種方便的處理,所以Windows注冊表對應用程序的重要性就顯而易見了。
原來的 Win16程序存儲私有信息是在一個平面文件INI中,這樣做有很多弊端,例如該INI文件沒有任何安全機制,用戶可以直接在INI文件中修改各種參數(shù)和程序入口,這樣就可能造成不可估計的嚴重后果,還有該文件只能支持和文本數(shù)據(jù)不能存入二進制數(shù)據(jù)等各種不利因素,所以微軟的工程師也認識到這一點,于是注冊數(shù)據(jù)庫就誕生了,注冊數(shù)據(jù)庫就是為了解決在 Windows 3.x 的一些關(guān)于 OLE 的此類問題而創(chuàng)建的,現(xiàn)在 Win32 應用程序的注冊數(shù)據(jù)庫通過微軟帶給我們的新的 Win32 API 得到了顯著的改善。使用訪問注冊表的 Win32 函數(shù)比起使用管理 INI 文件的 Win16函數(shù)要靈活的多,這意味著在功能上將大大增強,但是,另一方面,如果你還未用過,就會對處理注冊表的Win32 API 的新規(guī)則感到困惑或不知所措。本文就是本著這一目的,逐步讓你懂得并掌握怎樣用 Win32API 函數(shù)來處理32位 Windows 程序注冊表的方法。
二 . 技術(shù)的實現(xiàn)原理
為了在以后自己編寫的程序中更多的體現(xiàn)模塊化思想以及使編程變得更加簡單,應盡可能的建立自己實現(xiàn)各種功能的類,以類作為實現(xiàn)應用程序各種功能的單位。 在此,可以創(chuàng)建一個包括注冊表許多常用功能而接口簡單的類庫,下面將建立 CMyRegKey類,對應用程序處理注冊表的具體細節(jié)進行封裝,從而在外部通過這個功能類方便地實現(xiàn)進行訪問注冊表信息的各種操作,在外部調(diào)用其成員函數(shù)即可。以后,你就可以在每一個應用程序中包含此類并用其外部接口進行編程了。
三 . 實現(xiàn)代碼與步驟
1. 建立功能類的頭文件:
創(chuàng)建一個新的頭文件 MyRegKey.h ,在其中加入以下的代碼。
#include "winreg.h"
// 包含頭文件 winreg.h , 因注冊表Win32 API 函數(shù)在其內(nèi)定義
// 建立 CMyRegKey 類:
class CMyRegKey
{
// Construction
public:
CMyRegKey();
virtual ~CMyRegKey ();
// Attributes
public:
// 定義打開和關(guān)閉注冊表的成員函數(shù):
LONG RegRegOpen(HKEY hKeyRoot,LPCTSTR pszPath);
void RegRegClose();
// 利用函數(shù)重載實現(xiàn)對注冊表鍵值(串值,二進制值,DWORD值 ) 的讀和寫:
LONG RegRead (LPCTSTR pszKey,DWORD& dwVal);
LONG RegRead (LPCTSTR pszKey,CString& sVal);
LONG RegRead (LPCTSTR pszKey,BYTE *pData,DWORD& dwLength);
LONG RegWrite (LPCTSTR pszKey,DWORD dwVal);
LONG RegWrite (LPCTSTR pszKey,LPCTSTR pszVal);
LONG RegWrite (LPCTSTR pszKey,const BYTE *pData,DWORD dwLength);
protected:
HKEY m_hKey;
CString m_sPath;
};
2. 建立功能類的Cpp文件定義 CMyRegKey類:
創(chuàng)建一個新文件 MyRegKey.cpp ,代碼如下:
#include "MyRegKey.h"
/////////////////////////////////////////////////////////////////////////////
// CMyRegKey
/////////////////////////////////////////////////////////////////////////////
CMyRegKey:: CMyRegKey()
{
m_hKey = NULL;
}
CMyRegKey:: ~CMyRegKey()
{
RegClose();
}
// 定義打開注冊表的函數(shù),RegOpen 函數(shù)帶有兩個參數(shù):指定要訪問注冊表根結(jié)點的 HKEY, 以及注
// 冊表中信息的全路徑。如果給入的路徑不存在,則需創(chuàng)建一個新路徑。從 RegCreateKeyEx API函數(shù)返// 回的 HKEY 作為 m_hKey 存儲。
LONG CMyRegKey::RegOpen(HKEY hKeyRoot,LPCTSTR pszPath)
{
DWORD dw;
m_sPath = pszPath;
return RegCreateKeyEx(hKeyRoot,pszPath,0L,NULL,REG_OPTION_VOLATILE,KEY_ALL_ACCESS,NULL,
&m_hKey,&dw);
}
void CMyRegKey::RegClose()
{
if(m_hKey)
{
RegCloseKey (m_hKey);
m_hKey = NULL;
}
}
LONG CMyRegKey::RegWrite(LPCTSTR pszKey,DWORD dwVal)
{
ASSERT(m_hKey);
ASSERT(pszKey);
ASSERT(pData&&dwLength>0);
ASSERT(AfxIsValidAddress(pData,dwLength,FALSE));
return RegSetValueEx(m_hKey,pszKey,0L,REG_DWORD,(CONST BYTE *)&dwVal,sizeof(DWORD));
}
LONG CMyRegKey::RegWrite(LPCTSTR pszKey,LPCTSTR pszData)
{
ASSERT(m_hKey);
ASSERT(pszKey);
ASSERT(pszData);
ASSERT(pData&&dwLength>0);
ASSERT(AfxIsValidAddress(pszData,strlen(pszData),FALSE));
return RegSetValueEx(m_hKey,pszKey,0L,REG_SZ,(CONST BYTE *)pszData,strlen (pszData)+1);
}
LONG CMyRegKey::RegWrite(LPCTSTR pszKey,const BYTE *pData,DWORD dwLength)
{
ASSERT(m_hKey);
ASSERT(pszKey);
ASSERT(AfxIsValidAddress (pData,dwLength,FALSE));
ASSERT(pData&&dwLength>0);
ASSERT(AfxIsValidAddress(pData,dwLength,FALSE));
return RegSetValueEx(m_hKey,pszKey,0L,REG_BINARY,pData,dwLength);
}
LONG CMyRegKey::RegRead (LPCTSTR pszKey,DWORD& dwVal)
{
ASSERT(m_hKey);
ASSERT(pszKey);
DWORD dwType;
DWORD dwSize = sizeof (DWORD);
DWORD dwDest;
LONG LRet = RegQueryValueEx(m_hKey,(LPSTR)pszKey,NULL,&dwType,(BYTE *)
&dwDest,&dwSize);
if(LRet==ERROR_SUCCESS)
dwVal = dwDest;
return LRet;
}
LONG CMyRegKey::RegRead (LPCTSTR pszKey,CString& sVal)
{
ASSERT(m_hKey);
ASSERT(pszKey);
DWORD dwType;
DWORD dwSize = 200;
char string[200];
LONG IReturn = RegQueryValueEx(m_hKey,(LPSTR)pszKey,NULL,&dwType,(BYTE *)
string,&dwSize);
if(IReturn==ERROR_SUCCESS)
sVal = string;
return IReturn;
}
LONG CMyRegKey::RegRead (LPCTSTR pszKey,BYTE * pData,DWORD& dwLen)
{
ASSERT(m_hKey);
ASSERT(pszKey);
DWORD dwType;
return RegQueryValueEx(m_hKey,(LPSTR)pszKey,NULL,&dwType,pData,&dwLen);
}
在用戶需要使用時只需在你的 Project 中的 SorceFile 和 HeadFile 中分別加入 MyRegKey.cpp 以及 MyRegKey.h 程序文件。
四 . 使用外部接口示例
在VC中建立一個基于對話框(Dialog Base) 的應用程序,在對話框上放上幾個Edit control 的控件,如同示例小程序 RegTech 框(見圖一), 程序執(zhí)行時,首先讀出注冊表信息分別顯示在三個編輯欄中,為了演示寫入操作,你可以在注冊用戶欄中重新輸入用戶名,按更改完成寫入,重新運行程序,查看寫入是否成功。在RegTech 框中安置了三個編輯欄,ID 為 IDC_INSTALL,IDC_USERID,IDC_VERSION,
用ClassWizard 的Member Variable 分別加上對象參數(shù):m_Install, m_UserID 和 m_Version.
用參數(shù)來傳遞注冊表鍵值。
在初始化對話框時就應打開注冊表并讀取所需的信息,這三項存放路徑為HKEY_LOCAL_MACHINE \SOFTWARE \Microsoft \Windows \CurrentVersion下,
分別讀出windows 版本號(放置于Version鍵值中),注冊用戶名(放置于RegisteredOwner鍵值中),Windows 安裝目錄(放置于SystemRoot 鍵值中 ),更多的信息請使用Windows 目錄下的 RegEdit.exe程序.
需用到注冊表類的原程序文件中加上 #inxlude " MyRegKey.h" 即可。
在文件 RegTechDlg.cpp 中初始化對話框的地方加上以下代碼打開路徑并讀取鍵值:
BOOL CRegtechDlg::OnInitDialog()
{
CDialog::OnInitDialog();
......................
......................
// TODO: Add extra initialization here
//###########################################
// 打開注冊表路徑 .
CMyRegKey regKey1,regKey2,regKey3;
regKey1.RegOpen(HKEY_LOCAL_MACHINE,
_T("Software\\Microsoft\\Windows\\CurrentVersion"));
regKey2.RegOpen(HKEY_LOCAL_MACHINE,
_T("Software\\Microsoft\\Windows\\CurrentVersion"));
regKey3.RegOpen(HKEY_LOCAL_MACHINE,
_T("Software\\Microsoft\\Windows\\CurrentVersion"));
// 讀取鍵值并分別傳遞到編輯控件參數(shù)中去:
regKey1.RegRead(_T("Version"),m_Version);
regKey2.RegRead(_T("RegisteredOwner"),m_UserID);
regKey3.RegRead(_T("SystemRoot"),m_Install);
UpdateData(FALSE);
//############################################
return TRUE; // return TRUE unless you set the focus to a control
}
在重新輸入了注冊用戶名后,按下更改按鈕(按鈕控件ID_ChangeID),將完成注冊表的寫入操作:
void CRegtechDlg::OnChangeID()
{
//########################
CMyRegKey regKey;
regKey.RegOpen(HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"));
// 傳遞從編輯攔輸入的值并寫入打開路徑的指定鍵值名中:
UpdateData(TRUE);
regKey.RegWrite(_T("RegisteredOwner"),m_UserID);
MessageBox("更改注冊用戶名完畢!","Message",MB_ICONINFORMATION MB_OK);
///#########################
// TODO: Add your control notification handler code here
}
注冊表類在實際應用程序編制中使用頻率極高,比如程序員自定義的文件的圖標選擇等的很多地方都要用到,所以一個成熟優(yōu)秀的應用程序應盡可能的適應環(huán)境及發(fā)揮操作系統(tǒng)的各種優(yōu)勢,在此,使用win32 API對Windows靈魂--注冊表存取技術(shù)的操作已完成 ,你就可以利用它來完善自己的應用程序了。