Application Development

Software technique, Skills & Applications

BCB数据库图像保存技术 November 26, 2009

Filed under: C++Builder — meetme @ 1:16 pm

BCB数据库图像保存技术
  加上头文件#include<jpeg.hpp>
  1
  void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
  {
   OpenDialog2->FileName=”";
   if (OpenDialog2->Execute())
   {
   String f=OpenDialog2->FileName;
   if (FileExists(f))
   {
   String ext=ExtractFileExt(f).LowerCase();
   if (ext==”.bmp” || ext==”.jpg”|| ext==”.jpeg”)
   {
   String jpg=ChangeFileExt(ExtractFileName(f),”.jpg”);
   TJPEGImage *j=new TJPEGImage;
   if (ext==”.bmp”)
   {
   Graphics::TBitmap *b=new Graphics::TBitmap;
   b->LoadFromFile(f);
   j->Assign(b);
   j->CompressionQuality=90;
   j->Compress();
   delete b;
   }
   else
   {
   TFileStream *fs=new TFileStream(f,fmOpenRead);
   j->LoadFromStream(fs);
   delete fs;
   }
   DataModule1->ADODataSet1->Edit();
   DBEdit2->Text=jpg;
   TStream *bs=DataModule1->ADODataSet1->CreateBlobStream(
   DataModule1->ADODataSet1->FieldByName(“照片图像”),bmReadWrite);
   bs->Position=0;
   j->SaveToStream(bs);
   delete j;
   delete bs;
   DispJpg();
   }
   }
   }
  }
  2
  记住一定要在post前delete TADOBlobStream对象。
  //读
  TBlobField * pField=(TBlobField *)pQuery->FieldByName(“Image”);
  TADOBlobStream* pmem=new TADOBlobStream (pField,bmRead);
  pmem->Seek(0,soFromBeginning);
  Graphics::TBitmap * pBitmap=new Graphics::TBitmap();
  pBitmap->LoadFromStream(pmem);
  Image1->Picture->Assign(pBitmap);
  delete pBitmap;
  delete pmem;
  //写
  pQuery->Edit();
  TBlobField * pField=(TBlobField *)pQuery->FieldByName(“Image”);
  TADOBlobStream * pmem=new TADOBlobStream (pField,bmWrite);
  pmem->Seek(0,soFromBeginning);
  Graphics::TBitmap * pBitmap=new Graphics::TBitmap();
  pBitmap->Assign(Image1->Picture->Graphic);
  pBitmap->SaveToStream(pmem);
  delete pBitmap;
  delete pmem;
  pQuery->Post();
  如果你在ttable中用了固定字段,就更简单了,以下的ADOTable1pic字段就是
  读取access中的blob数据
  TMemoryStream *s = new TMemoryStream();
  ADOTable1pic->SaveToStream(s);
  s->Position=0; //****流首位置必须为零***
  TJPEGImage *jp = new TJPEGImage();
  jp->LoadFromStream(s);
  Image1->Picture->Bitmap->Assign(jp);
  delete jp;
  delete s;
  写数据到access的blob字段
  if (OpenDialog1->Execute())
  {ADOTable1->DisableControls();
  ADOTable1->Append();
  ADOTable1pic->LoadFromFile(OpenDialog1->FileName);
  ADOTable1name->Value=OpenDialog1->FileName;
  ADOTable1->Post();
  ADOTable1->EnableControls();
   }
  3
  void __fastcall TForm2::DBImage2Click(TObject *Sender)
  {
   try
   {
   if(OpenPictureDialog1->Execute());
   {
   AnsiString MyFilesExtension = UpperCase(ExtractFileExt(OpenPictureDialog1->FileName));
   if(MyFilesExtension==”.JPG”)
   {
   TJPEGImage *jpg=new TJPEGImage();
   jpg->LoadFromFile(OpenPictureDialog1->FileName);
   Clipboard()->Assign(jpg);
   DBImage1->DataSource->DataSet->Edit();
   DBImage1->PasteFromClipboard();
   DBImage1->DataSource->DataSet->Post();
   delete jpg;
   }
   if(MyFilesExtension==”.BMP”)
   {
   EditDataSource1->DataSet->Edit();
   DataModule1->FindADODataSetDSDesigner7->LoadFromFile(OpenPictureDialog1->FileName);
   }
   }
   }
   catch(…)
   {
   StatusBar1->Panels->Items[1]->Text=”保存图像发生异常”;
   }
  }
  4
  在BCB中采用下术方法存入图片,不过显示代码不用写了,DBImage自动显示.
  if(OpenPictureDialog1->Execute());
   {
   AnsiString MyFilesExtension = UpperCase(ExtractFileExt(OpenPictureDialog1->FileName));
   if(MyFilesExtension==”.JPG”)
   {
   TJPEGImage *jpg=new TJPEGImage();
   jpg->LoadFromFile(OpenPictureDialog1->FileName);
   Clipboard()->Assign(jpg);
   DBImage1->DataSource->DataSet->Edit();
   DBImage1->PasteFromClipboard();
   DBImage1->DataSource->DataSet->Post();
   delete jpg;
   }
  数据类型一定要是image
  存jpeg到SQL数据库:
  if(OpenPictureDialog1->Execute())
   {
   ADOQuery1->Edit();
   TBlobField *Field = (TBlobField*)ADOQuery1->FieldByName(“photo”);
   Field->LoadFromFile(OpenPictureDialog1->FileName);
   ADOQuery1->Post();
   }
  //以下是从数据库读jpeg,并显示在TDBImage控件中
  #include <clipbrd.hpp>
   TStream *Stream1;
   TJPEGImage *Pjp;
   Pjp=new TJPEGImage();
   ADOQuery1->Open();
   try
   {
   Stream1=ADOQuery1->CreateBlobStream(ADOQuery1->FieldByName(“treenodes”), bmRead);//treenodes是存放jpeg内容的字段,它的类型一定要用image
   Pjp->LoadFromStream(Stream1);
   //Image2是TDBImage组件,它的DateSource,和FieldName属性要空着
   Image2->Picture->Bitmap->Assign(Pjp);
   delete Stream1;
   }
   __finally
   {
   ADOQuery1->Close();
   delete Pjp;
   }
  下面是别人的更好的方法,可存各种图形
  以下是讀出各種類型的圖片的程序,支持ADO,BDE或TClientDataSet
  #define PICTURE_MAP__(TBit) {TBit *PG = new TBit(); try {PG->LoadFromStream(TmpStream); Pic->Assign(PG); } catch(…) {delete PG ; return false; } delete PG; }
  //—————————————————————-
  //該模板將二進制字段中的圖像(GIF或JPG等等)使用Assign方法轉為TPicture,TBitmap等等。
  template <class T >
  bool LoadPhotoFromField(TField *F_Photo,const AnsiString Format,T *Pic)
  {if(!F_Photo->DataSet->Active) return false ;
  if(F_Photo->IsNull) return false ;
  else
   {TStream *TmpStream = F_Photo->DataSet->CreateBlobStream(F_Photo,bmRead);
   if(Format == “.JPG” || Format == “.JPEG”)PICTURE_MAP__(TJPEGImage )
   else if(Format == “.BMP”) PICTURE_MAP__(Graphics::TBitmap)
  // else if(Format == “.GIF”) PICTURE_MAP__(TGIFImage )
   else if(Format == “.ICO”) PICTURE_MAP__(TIcon)
   else if(Format == “.WMF” || Format ==”.EMF”) PICTURE_MAP__(TMetafile)
   else return false ;
   }
  return true;
  }
  #undef PICTURE_MAP__(TBit)
  //如果要支持GIF,那你要安裝支持GIF的VCL類。
  支持多種格式
  存入:
  if(OpenPictureDialog1->Execute())
   {DataSet->Edit();
   TBlobField *Field = (TBlobField*)DataSet->FieldByName(“photo”);
   Field->LoadFromFile(OpenPictureDialog1->FileName);
   DataSet->FieldByName(“photoFormat”)->AsString =
   ExtractFileExt(OpenPictureDialog1->FileName).UpperCase();
   DataSet->Post();
   }

//

//

 

Vista+XP 双系统 安装方法 (本人亲测) November 14, 2009

Filed under: Vista — meetme @ 3:20 am

http://acerbbs.zol.com.cn/frmView.php?frameon=yes&subcatid=218&bookid=343076&ref0=http://www.google.ca/search?hl=en&q=acer+xp%E5%90%AF%E5%8A%A8%E8%80%81%E6%98%AF%E8%AF%B4%E7%BC%BA%E5%B0%91ntldr%E6%96%87%E4%BB%B6&meta=&aq=f&oq

Vista+XP 双系统 安装方法 (本人亲测)

Vista+XP 双系统 安装方法  (本人亲测)
图片在附件有

本人的电脑是 宏碁4920G  5A1G16Mi
Vista虽然很华丽,但XP还是用得比较顺手,
所以老早就想装个Vista+XP 双系统啦
经过本人在网上搜到的大量资料
经过两天晚上的奋斗,都快成熊猫了
不过好好总算成功啦。。^_^
所以和大家分享一下。。
首先列一下要用到的软件列表
1  Acer OEM Windows XP With SP3完美版
ed2k://|file|ACER_WINXP_PRO_SP3.iso|730869760|F56328A7A8D1A07B1A629EE23C9703B5|/  
其他版本大家也可以试试,只要大家能保证不会装在C盘或隐藏盘
我是刻盘后光驱安装在D盘的。。
2  Acronis Disk Director Suite v10.0.2160 简体中文汉化版
http://x.102.xdowns.com/102x/x/078/x-AcronisDiskDirectorCH.rar
建议能给XP分个10G的盘,但不要过大,过大会影响XP速度!
(冒似这个中文版能用,不会用的朋友可以去看看 毒毒大哥的帖子
http://nbbbs.zol.com.cn/4/218_338157.html
3  .NET Framework 2.0
http://www.onlinedown.net/soft/38669.htm
4  VistaBootPRO 3.1
http://www.onlinedown.net/soft/49400.htm
5  vista优化大师
6  Acer windows XP 驱动
http://nbbbs.zol.com.cn/34/218_339982.html

好,工作开始啦。。
把电脑调为光驱启动,放入Acer OEM Windows XP With SP3光盘
重启,进入光盘引导页面
晕,是英文的。。
按F4,就是进人Windows XP With SP3的安装页面,
。。。选择你要安装的盘 如D
好。。安装开始啦。。
大概5分钟后重启,再次进入光盘引导页面
此时就不要再按F4啦,按F4只会再重复上面的操作,
应该按 Esc 进入HDD 就是硬盘启动
好,XP继续进行安装。。。
XP安装好后,你就会发现进不了Vista 系统啦
这时你就要XP里安装
后装XP,则开机不会出现选择画面,而是直接进入XP,这样就进不了vsita了。
先装.NET Framework 2.0,再装VistaBootPRO 3.1
然后执行VistaBootPRO 3.1 软件
第一个画面是:

直接点击”ok”就可以了。。。
第二个画面是:

点击”system Bootloader”
第三个画面是:

选择”windows Vista Bootloader(Uninstall Legacy  Bootloader)”和”system Partition” 要选择这两个选项
然后点击右下角的”install bootloader”
在然后点击”diagnostice”选项卡,将出现第四个画面
第四个画面是:

直接点击”ok”就可以了。。。
第五个画面是:

直接点击”ok”就可以了。。。
第六个画面是:

这个画面可以修改,在开机的时候的多系统选项的名字,要是不想修改了,直接点击右下角的”apply updates”
注意哦!!
这时的XP启动盘也应该是C盘的,具体的我不知道是怎么回事,但网上有说过
当时我好像就是选择了D盘,才出现了,麻烦事。。
上边的步骤都执行完后,就可以重新启动电脑,就有多系统的选折项了。可爱的vista的画面又可以出现了。呵呵。。。

不过如果你重启后发现XP又启动不了,只能进入vista
这就是我刚才说的麻烦事,不怕,还有我(叔叔)教你,^_^
下面就是vista优化大师 出场啦
在Windows Vista 系统打开Vista优化大师,采用如下步骤:
  1、点击左侧的”系统设置”
  2、点击下面的”系统启动设置”
  3、点击右侧的”多系统选择”
  4、点击底下的”添加”,详细见下图–(

5,下面就是修改XP启动啦  单击选XP后
在按下面的修改
出现下图

把系统位置 改为 C 即可 ,不管你XP装在哪,都选C  !!
6, 下面还有一项要做就是进入硬盘D 搜索 ntldr
找到后复制到 C盘下,直接C:   即可
最好设置一下属性,隐藏,以防误删。。
呵呵。。。
那好,现在就大功啦,
关掉电脑再试试看,是不是 vista和 XP 都能正常启动啦
呵呵。。
下面就进入XP吧。。
把XP的全部驱动都装上去。。。
接下来就是自己玩XP咯。。
如果大家还有什么问题,
可以给我留言,我会尽量帮助大家解决

呵呵。。
不过我的XP现在还上不了网
不知是什么问题
主板驱动,(含无线)网卡驱动,都装啦
就是连不上
如果那位大虾告诉小弟一声
呵呵。。。
还有就是装完XP的时候会多了一个Windows Recovery Environment 启动项目,
就是vista优化大师启动栏看到的第三项。。
可以进去但是是英文的,看不懂呀
在网上查拉下
据说是基于Windows 预安装环境(WinPE)的恢复平台,它提供两个主要的功能:
1、使用启动修复工具自动诊断和修复启动问题。
2、高级恢复工具的集中平台
但是没中文看懂用
哪位大哥懂得,教一下大家。。
不然就等俺过了英语四级再说吧,哈哈

最后就是祝大家XP用得开心。。
过些天我会试试双系统的备份
有兴趣的朋友一起来研究。。
                                                  ONE421
                                                  08.07.30

 

http://bbs.cfan.com.cn/thread-563391-1-1.html

有VISTA的PC上再安装XP并设成双启动

如今,越来越多的PC在出厂时预装Windows Vista,这在很大程度上给用户带来了方便——虽然预装的Windows Vista多为Home Basic之类简化版本——不过,对许多用户而言,也许更习惯于Windows XP,加上日常使用的某些应用软件可能在Windows Vista中运行不太正常,因此,很多人希望在能系统中安装Windows XP,当然,前提是不影响系统中预装的Windows Vista,毕竟那是花钱买的。  
  在Vista天地网站的留言及收到的咨询E-mail中,涉及这个问题的比例很大,许多用户想知道怎样在预装Windows Vista的PC上安装Windows XP,并设置双重启动分别进入不同的系统,鉴于我们精力有限,不能一一回复。因此,在此作一简单总结,介绍在预装Vista的PC上安装Windows XP的基本思路,希望能对朋友们有所助益。
  警告:不要在预装Windows Vista的PC直接安装Windows XP

  众所周知,微软在Windows Vista中采用了全新的系统启动管理机制、全新的BootLoader,迥异于自Windows NT以来包括Windows 2000 /XP /2003中使用的ntldr,因此,直接在预装Windows Vista的PC安装Windows XP将破坏Windows Vista的Boot Loader,正如我们在Vista天地Windows Vista安装教程中所言的那样:
  如果您希望在PC中同时使用多个操作系统,必须保证Windows Vista是最后安装的系统,不然,比如说如果在安装Windows Vista后再安装Windows XP,将会造成Windows Vista的boot loader被ntldr+boot.ini覆盖,导致Windows Vista无法启动。
  这一点希望谨记。
  如何在预装Vista的PC上安装Windows XP

  下面介绍在预装Vista的PC上安装Windows XP的设置步骤:
  1、如果您的PC硬盘在出厂时已分割了多个分区,可直接跳到“安装Windows XP”;

  2、为Windows XP准备单独的安装分区

  很多PC的出厂设置中,硬盘未进行分区,即系统中仅包含“c:”盘,尤其在大部分笔记本电脑上极其普遍。在这种情况下,需要首先分割硬盘,为Windows XP准备一个单独的分区。
  打开磁盘管理器,在“C:”盘上单击右键,选择弹出菜单中的“压缩卷”,缩小Windows Vista所占用的分区,为新建分区调整出空间。注意:需为Windows Vista分区保留足够的可用空间;

  在调整出的“未分配的磁盘空间”上单击右键,选择“新建卷”,创建用于安装Windows XP的新分区;

  (详细操作步骤可参考Vista天地使用磁盘管理器调整硬盘分区中的介绍)

  推荐:最好重新调整系统盘符,对原来只有一个分区的系统而言,往往采用硬盘为“c:”盘,而DVD为“d:”盘的设置,这样,新建的硬盘分区盘符则依顺序被排为“e:”盘,在某些情况下可能会存在某种隐患。因此,建议在此时应重新调整盘符,比如将硬盘分区设为“c:”“d:”,而将DVD盘符调整为“e:”。虽然这一步不是必须要做的。

  要调整系统盘符设置,在磁盘管理器中选中相应分区,右键单击选择“更改驱动器号和路径”即可。当然,对于上述情况,即DVD已占用盘符“d:”的情况,可首先将DVD调整到一个未使用的盘符,如“z:”,然后,在将新建的硬盘分区盘符设置为“d:”,释放出占用的“e:”盘符后再调整回来。

  关闭磁盘管理器,重新启动Windows Vista。注意,要让Windows Vista接受修改后的硬盘设置,系统可能需重启两次。 3、安装Windows XP

  接下来,便可像往常一样安装Windows XP了,将Windows XP安装光盘放入DVD/CD驱动器中,设置从光驱引导,进行相应的安装即可。惟一需要注意的是,将Windows XP安装到新创建的硬盘中。

  4、重建Windows Vista的Boot Loader并设置双重启动

  正如上文所言,安装Windows XP后,系统中预装的Windows Vista将因Boot Loader被覆盖而无法启动,虽然Windows Vista存在于系统中。这时,便需要使用第三方工具来重建Boot Loader,并建立双重启动菜单以分别启动进入Windows Vista与Windows XP。可以实现这一功能的第三方软件有很多,如VistaBootPRO。下面简单介绍使用VistaBootPRO重建Boot Loader及设置双重启动。
  1、在Windows XP中下载、安装VistaBootPROVistaBootPRO,注:Windows XP需能够支持.Net Framework 2.00;

  2、运行VistaBootPRO,在Bootloader标签页中点击“Reinstall the Vista bootloader”,以重建Windows Vista的BootLoader,让系统能够启动进入Windows Vista。注意,仅完成这一步只能让系统启动进入Windows Vista,而无法启动Windows XP,接下来还要设置双重启动。

图1

  3、点击“Diagnostics”菜单项中的“Run Diagnostics”,让VistaBootPRO找到系统中存在的除Windows Vista之外的其他OS,待分析完成后即可看到除“Microsoft Windows Vista”外,还有名为“Earlier versions of Windows”的一项,此即是我们新安装的Windows XP,点击“Apply”即完成对Windows Vista与XP双重启动的设置。——当然,如果您愿意,也可以在此界面设置默认启动的系统、菜单延时等具体细节。

图2

  如此,即完成在预装Windows Vista的PC上安装Windows XP及设置双重启动分别引导进入两个系统的操作了,您可以在享受系统预装的Windows Vista的同时,继续使用更习惯、操作更熟练的Windows XP。

 

Bcb 读取文件的大小 September 23, 2009

Filed under: C++Builder — meetme @ 11:09 am

没有直接的函数返回文件的大小。上面的GetFileSize需要先打开文件,最后关闭文件。我觉得最简单的函数大概是stat函数了。  
  struct   stat   sb;  
  stat(FileName,   &sb);  
  //sb.st_size   就是文件的大小   (用到的头文件是   sys\stat.h)

 

在C++Builder中取得命令行参数 July 29, 2009

Filed under: C++Builder — meetme @ 1:14 am

原作者:抱雪http://win.chinaunix.net/bbs/thread-1237-1-1.html

用过C语言编程的人都知道,在DOS下的编程可以通过main函数的参数取得命令行参数的个数以及每个参数的字符串,例如

int main(int argv ,char *argv[])
{

}

  则命令行参数是argc个,这些参数分别存储在argv[0]~argv[argc-1]中,其中argv[0]是可执行文件的名字(含路径),那么 Windows程序是怎么取得命令行参数的呢?用C语言写过windows程序的人都知道,在windows程序的主函数WinMain()中,有一个参数lpszCmd,这个参数就是命令行参数。但我们在windows编程时一般都没在WinMain()函数工作,再加上lpszCmd是整个命令行,要取得每个参数使用也不方便,有没有更好的方法呢?

  如果你是使用的C++Builder编程,那么我就恭喜你,在C++Builder中用使用命令行参数是非常简单。C++Builder定义了三个全局变量和函数CmdLine、ParamStr()、ParamCount(),有了这三个变量和函数,就可以非常方便地使用命令行参数了,首先我们来看一下这几个函数和变量的定义:

extern PACKAGE char *CmdLine;
extern PACKAGE AnsiString __fastcall ParamStr(int Index);
extern PACKAGE int __fastcall ParamCount(void);

  CmdLine和WinMain()的参数lpszCmd是一样的,也就是整个命令行参数;ParamCount()用来取得命令行参数的个数,但不包括可执行文件名,也就是相当于DOS下的argc-1,ParamSter()用来取得每一个命令行参数的值,ParamStr(0)就是可执行文件名,实际的参数就是ParamStr(1)~ParamStr(ParamCount())。下面就以一个例子来说明这三个函数变量的使用。

  在窗体上放置一个Label,用来显示总的命令行参数;再加入一个ListBox,用来显示每个参数,然后在窗体的onCreate事件中加入以下代码:

    Label1->Caption=CmdLine;
    for(int i=0;i<=ParamCount();i++)
        ListBox1->Items->Add(ParamStr(i));

  然后在菜单Run->Parameters…中修改命令行参数,然后运行程序……怎么样?够简单的吧!

 

Split String April 4, 2009

Filed under: C++Builder — meetme @ 12:19 am

10 楼hzbigdog(苦命的程序员)回复于 2004-03-15 16:37:10 得分 0

算了,就共享一下我得代码吧!不过要给分哦!  
  //将字符串拆解成数组,以Flag为分解标志  
  //例如:AnsiString   S   =   “asd,234,sdf,22″;  
                  TStringList   *T   =   new   TStringList;  
                  char   flag   =’,';  
                  ResolveString(&S,   T,   &flag);  
                  for   (int   i   =   0;   i   <   T->Count;   i++)  
                          T->String(i);//访问拆分好的字符串  
   
  void   ResolveString(AnsiString   *Source,   TStringList   *Aim,   char   *flag)  
  {  
          const   int   Count   =   Source->Length();  
          int   site   =   1,   Len   =   0;//当前截取的位置  
          AnsiString   astrTemp,   OutStr;  
   
          Aim->Clear();  
          //测试要分解为多少各子串  
          for   (int   i   =   1;   i   <=   Count;   i++)  
                  if   (*Source->SubString(i,1).c_str()   ==   *flag)   Len++;  
   
          //开始攫取字符  
          for   (int   i   =   0;   i   <   Len;   i++)//数组层循环  
          {  
                  for   (;   site   <=   Count;   site++)//字符层循环  
                  {  
                          astrTemp   =   Source->SubString(site,1);   //获取一个字符  
                          if   (*astrTemp.c_str()   ==     *flag)  
                          {       /*如果发现当前取到的为分隔符,那么条过分隔符,结束循环  
                                      并开始下一组字符串的截取*/  
                                  site++;  
                                  break;  
                          }  
                          OutStr   =   OutStr   +   astrTemp;//合并成字符串  
                  }  
                  Aim->Add(OutStr);  
                  OutStr   =   “”;  
          }  
  }Top

11 楼hzbigdog(苦命的程序员)回复于 2004-03-15 16:45:17 得分 0

一个小错误  
  //例如:AnsiString   S   =   “asd,234,sdf,22″;  
  中”asd,234,sdf,22″;最后必须加一个’,'。正确的是  
  AnsiString   S   =   “asd,234,sdf,22,”;  
  赫赫1;你也可以自己优化一下!

 

MS Access To MySql March 22, 2009

Filed under: Data migration, Misc, SQL — meetme @ 5:24 pm
Tags: ,
 

Windows® XP File Association Fixes March 14, 2009

Filed under: Errors — meetme @ 1:25 pm

Fax Document cannot be displayed because your operating system does not have a default viewer for fax documents (.tif files)

http://www.dougknox.com/xp/file_assoc.htm

 

C++Builder注册表编程实例详解 March 4, 2009

Filed under: Redister — meetme @ 2:50 pm

2003-08-19 16:16作者:马明臣出处:yesky责任编辑:方舟

 

一、注册表编程详解  Windows 注册表中包含了系统配置、机器硬件配置、 Win32 应用程序和用户的其他配置信息。许多高级一些的功能都要通过对注册表的操作来实现。在 WinAPI 中提供了 RegCgreateKey() RegOpenKey() RegQueryValue() 等函数操作注册表,但是用这些函数来操作注册表使用起来非常麻烦。而利用 C ++ Builder TREGISTRY 类,我们则可以轻松实现对注册表的操作。下面我先介绍一下 TRegistry 类使用方法。  1. 使用前的准备工作:  首先必须在程序开始处包含定义类模块的头文件:  其次在全程变量(即所有函数之前)创建类的一个实例(对象):实例名 =new TRegistry();  注意:我们不能用直接声明的方法生成 TREGISTRY 的实例,这与 VC ++中用 HKEY 直接生成实例的方法不同。必须采用 new 关键字生成 TREGISTRY 类的实例,然后将指针传递给声名的变量。采用这个方式声明后,实例的 RootKey 属性指向 HKEY_CURRENT_USER 根键,即默认操作是针对 HKEY_CURRENT_USER 进行的。  2. 常用属性和方法介绍:  (1) 当前根键属性( RootKey ):  RootKey 属性定义了注册表类实例当前根键,默认的是 HKEY_LOCAL_USER 如果我们需要在其它根键下对注册表进行操作,可以修改 RootKey 属性:根键名 ;  BCB 中对注册表根键共有以下几个定义: HKEY_CURRENT_USER HKEY_CLASSES_ROOT HKEY_LOCAL_MACHINE HKEY_USERS HKEY_CURRENT_CONFIG HKEY_DYN_DATA HKEY_USERS 。分别对应注册表中相应的主键。(该属性为 int 型)  (2)当前键值的文本描述属性( CurrentPath ):属性定义了注册表当前键值的文本描述,如 \HKEY_CURRENT_USER\Software\Borland CurrentPath=-Software\Borland- ,而 RootKey=HKEY_CURRENT_USER (该属性为 AnsiString 型)。  (3)是否使修改后的值立即反映到注册表中( LazyWrite ):  这个属性的作用是决定是否在执行写操作之后立即将所做的改动反映到实际的注册表中。这个属性的值在注册表对象构造时初始化为 true ,即不立即将所做的改动反映到实际的注册表中,而是在执行 CloseKey() 函数之后重写注册表,这样可以提高系统性能。但是,如果我们需要将修改立即反映到注册表(这在许多场合是必要的),则应当首先将 LazyWrite 属性设置为 false ,然后执行修改操作。  (4) 建立主键函数:  bool __fastcall CreateKey( 主键名 );  如果主键已经存在,就覆盖原主键。如在当前主键下建立“ MyReg ”主键,可用“ CreateKey(-MyReg-) ”,而“ CreateKey(-\\MyReg-) ” 则在当前根键下建立主键 MyKey

 

 

 

#include -registry.hpp-

 

TRegistry *

 

 

 

 

MyReg->RootKey=

 

 

CurrentPath

 

 

 

 

 

(5) 删除主键函数:  bool __fastcall DeleteKey( 主键名 );  如果参数为空字符串,则删除当前键值   (6) 打开主键函数 :  bool __fastcall OpenKey( 主键名,参数 );  此函数将定位到一个具体的主键位置,随后的操作(建立键值、删除键值以及在当前位置建立主键、删除主键)将以此主键为当前主键。参数为 True 则当主键不存在将建立这个主键,如果为 false 则不建立主键。  (7) 读取当前主键下 String 型的键值函数: 键值名 );  如: Edit1->Text=MyReg->ReadString(-MyString-);  将读取键值 MyString 的内容到文本框 Edit1 中。 同此函数类似的还有 ReadBool() ReadInteger() ReadFloat() ReadDateTome() ReadBinaryData() 等,用来读出不同类型的键值。  (8) 在当前主键中写入 String 型键值函数:键值名,数据 );  如果是一个新键值名,那么相当于新建一个键值;如果是已有的键值,那么就是修改键值的数据。
如: WriteString(- 我的串 -,- 内容 -); 其它类型的键值(二进制值、 Dword 值)的读取和写入函数如 WriteInteger WriteBool() WriteFloat() WriteDateTome() WriteBinaryData() 等用法与上述类似。  (9) 判断键值或主键是否存在的函数:  bool __fastcall ValueExists( 键值名 );  这个方法判断当前键下是否存在指定的数据项,如果存在返回 true ,否则返回 false   bool __fastcall KeyExists( 主键名 );  这个方法判断一个键是否存在,如果存在返回 true ,否则返回 false   (10)从文件读入键值函数:  LoadKey( 键值名 , 文件名 ) ;

 

 

 

 

 

 

AnsiString __fastcall ReadString(

 

 

 

void __fastcall WriteString(

 

 

 

 

 

 

 

 

  (11)一个键值保存到文件函数:  SaveKey( 键值名 , 文件名 ) ;  (12) 关闭键值函数:  void __fastcall CloseKey(void);  在注册表使用完毕后,应当及时调用 CloseKey() 成员函数关闭注册表,并调用 delete 方法将用 new 申请的内存空间释放。  (13)当前主键下子键值的获取函数:

 

 

 

 

 

void __fastcall GetKeyNames(Classes::TStrings * Strings)   我们可以用该成员函数得到当前主键下所有子键的名称,用 GetKeyInfo 得到更加详细的信息。必须指出,虽然 GetKeyNames() 的说明成 void __fastcall GetKeyNames(Classes::TStrings * Strings) ,也就是说,它的参数类型是 TString ,但是我们并不能首先声明一个 TString 类的实例,然后将它作为参数用于 GetKeyNames() 。这主要是由于 TStrings 类含有抽象成分。我们的解决方法是采用 TStrings 类的派生类 TStringList 来代替 TStrings 声明一个实例,并作为参数用于 GetKeyNames() 函数。  在获得子键的名称后,我们就可以利用有关函数进一步确定详细信息。如用我们可以用 GetValueNames() 结合 Read() Write() 获得主键的值的详细信息。请看下面实例,这个例子的功能是将“ \Software\MyInfo ”主键下的所有子键名称显示在 ComboBox1 中:

 

 

include
…………
Tregistry * curReg=new TRegistry
() ;
curReg
>OpenKey( “ Software\\MyInfo-,true);
KeyNames=new TStringList();//
注意 TstirngList 类的声明方法!
curReg
>GetKeyNames(KeyNames); for(int i=0;iCount;i ++ ) ComboBox1 >Items >Add(KeyNames >Strings[i]);
curReg
>CloseKey();
delete KeyNames;

  3 使用 TRegistry 的一般步骤  一般来说,有以下四步操作:  1) 建立 TRegistry 类。 2) 利用 OpenKey() 方法打开一个键值。 3) ReadType() WriteType() 读写键值。 4) 调用 CloseKey ()关闭一个键值,最后调用 delete 方法将用 new 申请的内存空间释放。

 

 

二、应用实例1  下面我们通过一个示例程序演示了对注册表的常见操作,包括打开主键、读取不同类型的键值、删除键值或主键等。每次启动电脑自动运行复选框则实现的作用类似 Win 95 Welcome.exe 程序的功能。
首先在窗体添加 Edit1 Label1 label 2 (用于显示运行次数)、 Button1 CheckBox1 Caption= “每次启动电脑自动运行)等几个控件,然后添加以下源代码。生成可执行文件后,改名为 MyReg.EXE 拷贝到 C: 盘根目录下执行即可。  源代码:

 

 

//——————————————–
#include <vcl.h>
#pragma hdrstop
#include -registry.hpp- //
包含头文件
#include -Unit1.h-
//——————————————–
#pragma package(smart_init)
#pragma resource -*.dfm-
TForm1 *Form1;
TRegistry *MyReg=new TRegistry();//
建立实例
//——————————————–
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{}
//——————————————–
void __fastcall TForm1::FormCreate(TObject *Sender)
{MyReg->RootKey=HKEY_CURRENT_USER;
if((MyReg->OpenKey(-\\software\\MyReg-,false))==false)
{MessageBox(NULL,-
感谢第一次使用本软件 !.-,- 欢迎 !-,IDOK);
MyReg->CreateKey(-\\software\\MyReg-);
MyReg->OpenKey(-\\software\\MyReg-,true);
MyReg->WriteInteger(-Number-,0);
MyReg->WriteString(-The String-,Edit1->Text);
}//
检测有无注册表项 , 没有则建立
int num=MyReg->ReadInteger(-Number-);
num++;
MyReg->WriteInteger(-Number-,num);//
使用次数 +1 并写入注册表
Label2->Caption=IntToStr(num);
Edit1->Text=MyReg->ReadString(-The String-);
MyReg->CloseKey();
MyReg->RootKey=HKEY_LOCAL_MACHINE;
MyReg->OpenKey(-\\software\\Microsoft\\windows\\CurrentVersion\\Run-,false);
CheckBox1->Checked=MyReg->ValueExists(-AutoShow-);
MyReg->CloseKey();//
根据是否自动运行设定 CheckBox 状态
}
//——————————————–
void __fastcall TForm1::Edit1Change(TObject *Sender)
{MyReg->RootKey=HKEY_CURRENT_USER;
MyReg->OpenKey(-\\software\\MyReg-,false);
MyReg->WriteString(-The String-,Edit1->Text);
MyReg->CloseKey();//Edit1
改变写入注册表
}
//——————————————–
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{MyReg->RootKey=HKEY_LOCAL_MACHINE;
MyReg->OpenKey(-\\software\\Microsoft\\windows\\CurrentVersion\\Run-,false);
if(CheckBox1->Checked)
MyReg->WriteString(-AutoShow-,-c:\\MyReg.EXE-);
else MyReg->DeleteValue(-AutoShow-);
MyReg->CloseKey();//
如果 CheckBox 选中则自动运行 , 否则删除自动运行键值
delete MyReg;
}
//——————————————–
void __fastcall TForm1::Button1Click(TObject *Sender)//
单击 Button1 删除注册表项
{MyReg->RootKey=HKEY_LOCAL_MACHINE;
MyReg->OpenKey(-\\software\\Microsoft\\windows\\CurrentVersion\\Run-,false);
MyReg->DeleteValue(-AutoShow-);
MyReg->CloseKey();//*
删除自动运行键值
MyReg->RootKey=HKEY_CURRENT_USER;
MyReg->DeleteKey(-\\software\\MyReg-);//
删除注册表项
}

 

三、注册表编程实例2—— 编写输入法调序器  通常我们使用输入法时,要按下Ctrl+空格键多次才能找到自己所熟悉的输入法,那么我们能不能把自己最常用的输入法调到英文输入法后面呢?(即只按一下Ctrl+空格即可调出自己使用的输入法)笔者经过研究,终于设计出了一个输入法调序器。它可以把当前系统中的所有输入法全部列出来,并可自由调整输入法顺序。下面笔者就把实现方法介绍给大家。  程序实现原理:  我们知道在注册表HKEY_CURRENT_USER\keyboard layout\preload下有子键12345(这就是输入法的顺序),每个子键的缺省键值即为标识该输入法的串值,如串值00000409对应的是英文输入法,串值E0040804对应的是智能ABC输入法。如果想知道每一个串值对应什么输入法,我们可以在HKEY_lOCAL_MACHINE\System\CurrentControlSet\Control\Keyboard Layouts之下找到。知道了输入法的存放位置及顺序关系后,我们可以利用程序操作注册表把代表输入法顺序的串值进行相应移动,即可实现我们的目的了。  具体实现步骤:  1、新建一工程文件,在窗体上放入一个ListBox组件、三个BitBtn组件和一个Label组件。  2、在窗体的单元文件中定义全局变量如下:注册表对象
TRegKeyInfo keyInfo;//
主键信息变量  并在单元文件前部增加包含#include <Registry.hpp>  3、在窗体的OnCreate事件过程中输入如下代码

 

 

 

 

 

 

AnsiString *imeStr,temStr;
TRegistry *Reg1,*Reg2;//

 

 

void __fastcall TForm1::FormCreate(TObject *Sender)
{
Reg1=new TRegistry;//
创建注册表对象
Reg2=new TRegistry;
Reg1->RootKey=HKEY_CURRENT_USER;//
定位注册表根键
Reg2->RootKey=HKEY_LOCAL_MACHINE;
if(Reg1->OpenKey(“\\keyboard layout\\preload\\”,false)==true)
Reg1->GetKeyInfo(keyInfo);//
取得指定主键信息
ListBox1->Items->Clear();
imeStr=new AnsiString[keyInfo.NumSubKeys];//
动态创建数组
for(int i=0;i<keyInfo.NumSubKeys;i++)
{
if(Reg1->OpenKey(“\\keyboard layout\\preload\\”+IntToStr(i+1),false)==true)
imeStr[i]=Reg1->ReadString(“”);//
取得输入法串值
if(Reg2->OpenKey(“\\System\\CurrentControlSet\\Control\\Keyboard Layouts\\”+imeStr[i]+”\\”,false)==true)
ListBox1->Items->Add(Reg2->ReadString(“layout text”));//
显示输入法名称
}
Reg1->CloseKey();
Reg2->CloseKey();
delete Reg2;
}

  4、在BitBtr1(上移按钮)OnClick事件中加入如下代码

void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
int i=ListBox1->ItemIndex;//
当前选择的行号
if (i>0)
{
ListBox1->Items->Exchange(i,i-1);//
交换列表框中内两行的内容
temStr=imeStr[i];//
对应串值也交换
imeStr[i]=imeStr[i-1];
imeStr[i-1]=temStr;
}
}

  5、类似地,在BitBun2(下移)OnClick事件中加入如下代码

void __fastcall TForm1::BitBtn2Click(TObject *Sender)
{
int i=ListBox1->ItemIndex;//
当前选择的行号
if (i<ListBox1->Items->Count-1)
{
ListBox1->Items->Exchange(i,i+1);
temStr=imeStr[i];//
对应串值也交换
imeStr[i]=imeStr[i+1];
imeStr[i+1]=temStr;
}
}

  6、在BitBtn3(确认按钮)OnClick事件中加入如下代码

void __fastcall TForm1::BitBtn3Click(TObject *Sender)
{
if((Application->MessageBox(“
确认更改输入法顺序吗?“,”请确认“,MB_OKCANCEL|MB_ICONWARNING))==ID_OK)
{
for(int i=0;i<keyInfo.NumSubKeys;i++)
{
Reg1->OpenKey(“\\keyboard layout\\preload\\”+IntToStr(i+1),false);
Reg1->WriteString(“”,imeStr[i]);
}//
给输入法重新排序
Reg1->CloseKey();
delete Reg1;
delete imeStr;
if((Application->MessageBox(“
马上要重新启动计算机“,”重启计算机“,MB_OKCANCEL|MB_ICONWARNING))==ID_OK)
ExitWindowsEx(EWX_REBOOT,0);
}
Close();
}

  以上程序在Windows 98C++ builder6.0下调试通过。 

 

 

Match September 30, 2008

Filed under: Uncategorized — meetme @ 12:59 pm

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            string[] stdA = { “1″, “2″, “3″, “4″, “2″ };
            string[] optA = { “2″, “2″, “4″, “5″, “4″ };
            int[] stdU = { 0, 0, 0, 0, 0 };
            int[] optU = { 0, 0, 0, 0, 0 };

            int B = 0;
            int W = 0;

            for(int i=0;i < 5;i++)
            {
                if (stdA[i] == optA[i])
                {
                    B += 1;
                    stdU[i] = 1;
                    optU[i] = 1;
                }

                for (int j = 0; j < 5; j++)
                {
                    if (i != j)
                    {
                        if (stdA[i] == optA[j] && stdU[i] == 0 && optU[j] == 0)
                        {
                             W += 1;
                             stdU[i] = 1;
                             optU[j] = 1;
                         }
                    }
                }
            }

            Console.Write(“B=”+B.ToString() + “  W=”+W.ToString() );
            Console.Read();
        }
    }
}

 

如何在快速启动工具栏上重新创建显示桌面图标 September 20, 2008

Filed under: Misc — meetme @ 12:43 pm

请按照下列步骤,在“快速启动”工具栏上重新创建“显示桌面”图标:
1. 使用任何文本编辑器(如“记事本”),创建包含下列行的文件:
[Shell]
Command=2
IconFile=explorer.exe,3
[Taskbar]
Command=ToggleDesktop
2. 在 Windows\System 或 Winnt\System32 文件夹中,以 Show Desktop.scf 名称保存新文件。注意,“记事本”可能会自动将 .txt 作为文件扩展名。如果“记事本”添加了该扩展名,请将其删除。如果将文件命名为 Show Desktop.scf.txt,则这些步骤无效。
3. 退出“记事本”。
4. 使用 Windows 资源管理器或“我的电脑”,右键单击“Show Desktop .scf”文件,然后单击“创建快捷方式”。

5. 将新的快捷方式复制到相应的文件夹中。在 Microsoft Windows 95 或 Windows 98 中,将该快捷方式复制到以下文件夹中:
Windows\Application Data\Microsoft\Internet Explorer\Quick Launch
在 Microsoft Windows NT 或 Microsoft Windows 2000 中,将该快捷方式复制到以下文件夹中:
Winnt\System32
在 Microsoft Windows XP 中,将该快捷方式复制到以下文件夹中:
WINDOWS\System32\Config\Systemprofile\Application Data\Microsoft\Internet Explorer\Quick Launch
6. 重命名桌面快捷方式。
此时,“显示桌面”图标就会自动出现在“快速启动”工具栏上