C0EEBDA1

在梦中,我是有超能力的。。。

« 【随笔】一个很容易迷惑人的问题:“二维数组”和“指针的指针”【MFC应用】UTC(格林尼治时间)转换为本地时间 »

【MFC应用】使用CRegKey类操作注册表,完成文件关联

之前写过一个文章,介绍在windows下文件关联的实现机制《【MFC应用】文件关联》,这篇文章是介绍利用注册表实现文件关联的原理的,当初本来计划再写一篇文章,介绍MFC下的实现的,结果给忘了,唉,这脑子~~~~   今天看到有网友留言给我,才突然发现还没写过MFC的实现,所以,今天补上  ^_^

上一篇曾经介绍过,其实要实现文件关联,关键就是对注册表的操作。在MFC中,有个叫做CRegKey的类,封装了对注册表的操作,下面对这个类简单介绍一下:

1.简介

CRegKey提供了对系统注册表的操作方法,通过CRegKey类,可以方便的打开注册表的某个分支或子键(CRegKey::Open),可以方便的修改一个键的键值(CRegKey::SetValue),也可以查询某个键的键值(CRegKey::QueryValue),操作完成之后,可以关闭子键(CRegKey::Close)。

要想使用CRegKey类,需要包含头文件atlbase.h

2.常用操作方法

1) 打开需要查询或修改的注册表键

LONG Open( HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired = KEY_ALL_ACCESS );

hKeyParent参数指定了待打开的注册表键的句柄,常用的可选值为

HKEY_CLASSES_ROOT

HKEY_CURRENT_USER

HKEY_LOCAL_MACHINE

HKEY_USERS

以上四个值分别代表了注册表中最主要的四个分支;

lpszKeyName参数指定了在hKeyParent下需要打开的项的名字;

samDesired参数指定了打开该项后所拥有的权限,默认为KEY_ALL_ACCESS,表示拥有对该分支的所有操作权,包括读和写等。

 

举例:

   1: CRegKey myKey;
   2: if(myKey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows") != ERROR_SUCCESS)
   3: {
   4:     AfxMessageBox("Error open reg key!!");
   5: }

 

2) 查询注册表项中的某个键的键值

LONG QueryValue( DWORD& dwValue, LPCTSTR lpszValueName );

LONG QueryValue( LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount )

查询键值提供了两种形式,分别用来获取数值类型的值和字符串类型的值。在上面的形式中,第一种用于获取数值类型的值,第二种用于获取字符串类型的值。

lpszValueName参数用来指定键的名称,dwValue和szValue用于保存键值,而pdwCount用来控制获取到的字符串值的长度

 

举例:

比如,假设要获得windowx系统默认的桌面壁纸的搜索路径,由于这个路径保存在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion这一项的WallPaperDir键内,如下图

image

所以,可以用以下的代码来实现:

   1: CRegKey myKey;
   2: if(myKey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion") != ERROR_SUCCESS)
   3:     AfxMessageBox("Error open reg key!!!");
   4: else
   5: {
   6:     char szPath[MAX_PATH];
   7:     DWORD dwLen = myKey.QueryValue(szPath, "WallPaperDir", MAX_PATH);
   8: }

另外,如果我们想查询某个项的默认键值该怎么办呢?只需要将lpszValueName参数写为空字符串就好了。比如现在想看一下.txt类型的文件的关联程序是谁,我们需要首先在HKEY_CLASSES_ROOT下找到.txt项,然后看它的默认键值是多少:

image

示例代码如下:

   1: CRegKey myKey;
   2: if(myKey.Open(HKEY_CLASSES_ROOT, ".txt") != ERROR_SUCCESS)
   3:     AfxMessageBox("Error open key!!!");
   4: else
   5: {
   6:     char szFileType[255];
   7:     DWORD dwLen = myKey.QueryValue(szFileType, "", sizeof(szFileType));
   8: }

3) 添加或修改键值

LONG SetValue( DWORD dwValue, LPCTSTR lpszValueName );

LONG SetValue( LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL );

LONG SetValue( HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL );

添加键值函数提供了三种形式,前两种分别用来向当前已经打开的这个项中添加DWORD类型的键、字符串类型的键,最后一种形式的函数,可以在某个特定的分支线下的某个特定的项内添加一个键。如果lpszKeyName指定的键不存在,则添加这个键,否则,就是修改已经存在的键的键值。另外需要注意的是,最后一种形式的SetValue函数,如果lpszKeyName所指定的项不存在,则SetValue函数会返回错误,而不会添加一个项。

示例,比如现在要给IE的工具栏设置一个背景图片,可以在HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Toolbar项下面新建一个BackBitmap的字符串键,并制定背景图片的位置,代码如下:

   1: CRegKey myKey;
   2: if(myKey.Open(HKEY_CURRENT_USER, "Software\\Microsoft\\Internet Explorer\\Toolbar") != ERROR_SUCCESS)
   3:     AfxMessageBox("error open reg key!!!");
   4: else
   5: {
   6:     myKey.SetValue("C:\\WINDOWS\\Web\\Wallpaper\\Bliss.bmp", "BackBitmap");
   7: }

这样,IE的背景图片就被设置成了C:\WINDOWS\Web\Wallpaper\Bliss.bmp

4) 删除键值

LONG DeleteValue( LPCTSTR lpszValue );

这个函数比较简单,它会删除lpszValue参数指定的键。

 

5) 新建项

LONG Create( HKEY hKeyParent, LPCTSTR lpszKeyName, LPTSTR lpszClass = REG_NONE, DWORD dwOptions = REG_OPTION_NON_VOLATILE, REGSAM samDesired = KEY_ALL_ACCESS, LPSECURITY_ATTRIBUTES lpSecAttr = NULL, LPDWORD lpdwDisposition = NULL );

Create函数用于创建一个项,它可以在hKeyParent指定的分支下,创建一个名为lpszKeyName的项,后面几个参数一般用默认的即可。

比如,现在要建立一个新的文件类型.spj的关联方式,首先需要在HKEY_CLASSES_ROOT下建立一个名为.spj的项,代码如下:

   1: CRegKey myKey;
   2: if(myKey.Create(HKEY_CLASSES_ROOT, ".spj") != ERROR_SUCCESS)
   3:     AfxMessageBox("error create key!!!");
   4: else
   5:     AfxMessageBox("create key ok!");

6) 删除项

LONG DeleteSubKey( LPCTSTR lpszSubKey );

该函数可以删除名为lpszSubKey的项,以及该项下的所有的键。注意,被删除的项不能含有子项!可以通过另外一个函数LONG RecurseDeleteKey( LPCTSTR lpszKey );删除某个项以及该项下的所有内容。

 

7) 关闭注册表

LONG Close( );

关闭注册表时,之前所做的修改才会被保存到硬盘。或者,也可以使用LONG RegFlushKey( HKEY hKey ); 函数在需要的时候将所做的修改及时写入硬盘。

 

OK,有关CRegKey的介绍先告一段落。下面接着进行MFC下如何进行文件关联的操作。

其实,只要知道了CRegKey类的使用方法,文件关联的操作也就不难了。下面贴出来一个简单的文件关联的类,抛砖引玉:

   1: // RegRelateExt.h: interface for the CRegRelateExt class.
   2: //
   3: //////////////////////////////////////////////////////////////////////
   4:  
   5: #if !defined(AFX_REGRELATEEXT_H__6DE7E979_9011_4639_967A_D8817DF4DE44__INCLUDED_)
   6: #define AFX_REGRELATEEXT_H__6DE7E979_9011_4639_967A_D8817DF4DE44__INCLUDED_
   7: #include "ATLBASE.h"
   8:  
   9: #if _MSC_VER > 1000
  10: #pragma once
  11: #endif // _MSC_VER > 1000
  12:  
  13: class CRegRelateExt : public CRegKey  
  14: {
  15: public:
  16:     CRegRelateExt();
  17:     CRegRelateExt(CString FileExt, CString RelateExe = "LibMaker.exe");
  18:     virtual ~CRegRelateExt();
  19:     BOOL Check();
  20:     BOOL Check(CString FileExt);
  21:     BOOL Set(CString FileExt, CString ShellCmd);
  22:     BOOL Delete(CString FileExt);
  23:  
  24: private:
  25:     BOOL m_IfRelated;
  26:  
  27:     CString m_RegClass;
  28:     CString m_RelateExe;
  29: };
  30:  
  31: #endif // !defined(AFX_REGRELATEEXT_H__6DE7E979_9011_4639_967A_D8817DF4DE44__INCLUDED_)

上面是头文件,定义了CRegRelateExt类,这个类提供了几个操作方法,比如:Check用于检查某个扩展名是否与指定程序关联;Set用于将某个扩展名的文件与指定程序进行关联;Delete用于删除某个文件类型的关联。

   1: // RegRelateExt.cpp: implementation of the CRegRelateExt class.
   2: //
   3: //////////////////////////////////////////////////////////////////////
   4:  
   5: #include "stdafx.h"
   6: #include "LibMaker.h"
   7: #include "RegRelateExt.h"
   8:  
   9: #ifdef _DEBUG
  10: #undef THIS_FILE
  11: static char THIS_FILE[]=__FILE__;
  12: #define new DEBUG_NEW
  13: #endif
  14:  
  15: //////////////////////////////////////////////////////////////////////
  16: // Construction/Destruction
  17: //////////////////////////////////////////////////////////////////////
  18:  
  19: CRegRelateExt::CRegRelateExt()
  20: {
  21:     m_IfRelated = FALSE;
  22: }
  23:  
  24: CRegRelateExt::CRegRelateExt(CString FileExt, CString RelateExe)
  25: {
  26:     m_RelateExe = RelateExe;
  27:     Check(FileExt);
  28: }
  29:  
  30: BOOL CRegRelateExt::Check()
  31: {
  32:     return m_IfRelated;
  33: }
  34:  
  35: BOOL CRegRelateExt::Check(CString FileExt)
  36: {
  37:     if(m_RelateExe.IsEmpty())
  38:         return FALSE;
  39:  
  40:     if(Open(HKEY_CLASSES_ROOT, FileExt, KEY_READ) != ERROR_SUCCESS)
  41:         m_IfRelated = FALSE;
  42:  
  43:     DWORD ValueLen = MAX_PATH;
  44:     TCHAR Value[MAX_PATH];
  45:     if(QueryValue(Value, "", &ValueLen) != ERROR_SUCCESS)
  46:         m_IfRelated = FALSE;
  47:     Close();
  48:     m_RegClass = Value;
  49:  
  50:     if(Open(HKEY_CLASSES_ROOT, m_RegClass + "\\shell\\open\\command", KEY_READ) != ERROR_SUCCESS)
  51:         m_IfRelated = FALSE;
  52:  
  53:     ValueLen = MAX_PATH;
  54:     if(QueryValue(Value, "", &ValueLen) != ERROR_SUCCESS)
  55:         m_IfRelated = FALSE;
  56:  
  57:     Close();
  58:     CString CmdLine = Value;
  59:     if(CmdLine.Find(m_RelateExe) != -1)
  60:         m_IfRelated = TRUE;
  61:     else
  62:         m_IfRelated = FALSE;
  63:     return m_IfRelated;
  64: }
  65:  
  66: BOOL CRegRelateExt::Delete(CString FileExt)
  67: {
  68:     if(FileExt.IsEmpty())
  69:         return FALSE;
  70:  
  71:     if(Open(HKEY_CLASSES_ROOT, FileExt, KEY_READ) != ERROR_SUCCESS)
  72:         return FALSE;
  73:  
  74:     DWORD ValueLen = MAX_PATH;
  75:     TCHAR Value[MAX_PATH];
  76:     if(QueryValue(Value, "", &ValueLen) != ERROR_SUCCESS)
  77:         return FALSE;
  78:     Close();
  79:  
  80:     Attach(HKEY_CLASSES_ROOT);
  81:     if(RecurseDeleteKey(Value) != ERROR_SUCCESS)
  82:         return FALSE;
  83:  
  84:     if(RecurseDeleteKey(FileExt) != ERROR_SUCCESS)
  85:         return FALSE;
  86:  
  87:     return TRUE;
  88: }
  89:  
  90: BOOL CRegRelateExt::Set(CString FileExt, CString ShellCmd)
  91: {
  92:     if(FileExt.IsEmpty() || ShellCmd.IsEmpty())
  93:         return FALSE;
  94:  
  95:     m_RelateExe = ShellCmd;
  96:     m_RegClass = "S+core Arch File";
  97:     Delete(FileExt);
  98:  
  99:     if(Create(HKEY_CLASSES_ROOT, FileExt) != ERROR_SUCCESS)
 100:         return FALSE;
 101:     if(SetValue(HKEY_CLASSES_ROOT, FileExt, m_RegClass) != ERROR_SUCCESS)
 102:         return FALSE;
 103:     if(Create(HKEY_CLASSES_ROOT, m_RegClass) != ERROR_SUCCESS)
 104:         return FALSE;
 105:     if(SetValue(HKEY_CLASSES_ROOT, m_RegClass, "S+core Archive File") != ERROR_SUCCESS)
 106:         return FALSE;
 107:     if(SetValue((DWORD)0x08, "BrowserFlags") != ERROR_SUCCESS)
 108:         return FALSE;
 109:     if(SetValue((DWORD)0x00, "EditFlags") != ERROR_SUCCESS)
 110:         return FALSE;
 111:     if(SetValue(HKEY_CLASSES_ROOT, m_RegClass, "S+core Archive File") != ERROR_SUCCESS)
 112:         return FALSE;
 113:     if(Create(HKEY_CLASSES_ROOT, m_RegClass + "\\DefaultIcon") != ERROR_SUCCESS)
 114:         return FALSE;
 115:     if(SetValue(HKEY_CLASSES_ROOT, m_RegClass + "\\DefaultIcon", ShellCmd + ",1") != ERROR_SUCCESS)
 116:         return FALSE;
 117:     if(Create(HKEY_CLASSES_ROOT, m_RegClass + "\\shell") != ERROR_SUCCESS)
 118:         return FALSE;
 119:     if(Create(HKEY_CLASSES_ROOT, m_RegClass + "\\shell\\open") != ERROR_SUCCESS)
 120:         return FALSE;
 121:     if(Create(HKEY_CLASSES_ROOT, m_RegClass + "\\shell\\open\\command") != ERROR_SUCCESS)
 122:         return FALSE;
 123:     if(SetValue(HKEY_CLASSES_ROOT,m_RegClass + "\\shell\\open\\command", ShellCmd + " \"%1\"") != ERROR_SUCCESS)
 124:         return FALSE;
 125:     m_IfRelated = TRUE;
 126:     return TRUE;
 127: }
 128:  
 129: CRegRelateExt::~CRegRelateExt()
 130: {
 131:  
 132: }

  • quote 1.mmss
  • “这个其实可以在右键点击相应扩展名文件,
    选择打开方式,然后找到你的程序手工完成
    可是之后双击文件,程序只打开一个新文件,
    不会打开你双击的文件
    这个就需要你来把文件路径传给程序,具体实现可以不同的方法

    其中之一就是在Cxxxapp里的InitInstance()函数中实现该功能
    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);

    if (!ProcessShellCommand(cmdInfo))
    return FALSE;
    通过解析命令行参数,自己改写来实现吧”
    --------------以上是“硬石头”给的点拨,可是我还是没想出来
    请帮忙想想如何实现,如果能单独给我讲讲最好了----->---->]
    (注意:这是镜像)253250153:pp<----]
  • 2009-5-28 22:59:21 回复该留言
  • quote 2.mmss
  • 呀,写错了;
    (注意:这是镜像)253520153:pp
    lijian 于 2009-5-31 8:59:50 回复
    呵呵,没太看明白您是想要做什么? ^_^
  • 2009-5-28 23:03:13 回复该留言

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Spirit Build 80722 Code detection by Codefense  theme by BokeZhuti

Copyright 2008-2009 C0EEBDA1. Some Rights Reserved. 备案号:京ICP备09020681号