Application Development

Software technique, Skills & Applications

BCB September 19, 2007

meetme @ 9:12 pm

Unable to open SHEllCtrls.obj

1.首先我沒有將它 compiled 成獨立執行檔所以沒有 BCB 無法執行.

2.再來請開啟 BCB 然後在
Component->Install Component-> Into existing package
加入
C:\Program Files\Borland\CBuilder6\Examples\ShellControls\bcbshlctrls.bpk
這是 Borland 的 Example Object
我按照你说的方法在
Component->Install Component-> Into existing package
对话框中
Unit file name里找到
C:\Program Files\Borland\CBuilder6\Examples\ShellControls\bcbshlctrls.cpp
Package file name里输入
C:\Program Files\Borland\CBuilder6\Examples\ShellControls\bcbshlctrls.bpk

 

StringReplace
   
  StringReplace(PrintSetContent,   “e”,   “f”,   TReplaceFlags()   <<   rfReplaceAll);

 把字符串“26656.5”转换成“26.656.50”的货币型式
2 楼wenyongjie(我们的目标是:没有蛀牙!!)回复于 2003-02-22 17:24:14 得分 50我也是菜鸟,但我知道你的问题.  
  void   __fastcall   TForm1::Button1Click(TObject   *Sender)  
  {Label1->Caption=”26656.5″;  
    Label2->Caption=CurrToStrF(StrToCurr(Label1->Caption),ffCurrency,2);  
  }  

SHFILEINFO sfi;
SHGetFileInfo(
FileName.c_str(),
FILE_ATTRIBUTE_NORMAL,
&sfi,
sizeof(SHFILEINFO),
SHGFI_ICON
);
TIcon* picon = new TIcon();
picon->Handle = sfi.hIcon;
Image1->Canvas->Pen->Color = clWhite;
Image1->Canvas->Brush->Color = clWhite;
Image1->Canvas->Rectangle( 0, 0, 16, 16 );
Image1->Canvas->Draw( 0, 0, picon );
DestroyIcon( sfi.hIcon );
delete picon;

 

将e:\doc\doc1.doc”压缩为E:\c-51\doc1.rar

ShellExecute(NULL,”open”,”C:\\Program   Files\\WinRAR\\rar.exe”,”a   E:\\c-51\\doc1.rar   e:\\doc\\doc1.doc”,NULL,SW_HIDE);

还有一个问题想问一下,我用
ShellExecute(NULL,”open”,”C:\\Program   Files\\WinRAR\\rar.exe”,”x   E:\\c-51\\doc1.rar   e:\\c-51\\”,NULL,SW_HIDE);
进行解压后,会出现一个doc文件夹,然后doc1.doc文件在它目录下
怎么样可以直接把doc1.doc解压出来,而没有这个doc文件夹生成呢?

提示信息框(MessageBox)的应用

int __fastcall MessageBox(const char * Text,//提示信息框的内容

const char * Caption,                  //提示信息框的标题

int Flags);                            //提示信息框的类别

参数Flags的值是用来标志提示信息框的类别的,下面是一些常用的类别:

参数值

样式

意义

MB_ICONWARNING

含图标、固定按钮

警告信息框

MB_ICONQUESTION

含图标、固定按钮

疑问信息框

MB_ICONERROR

含图标、固定按钮

错误信息框

MB_ICONASTERISK

含图标、固定按钮

提示信息框

MB_HELP

不含图标、可改变按钮

说明信息框

MB_OK

不含图标、可改变按钮

提示信息框

MB_OKCANCEL

不含图标、可改变按钮

确认信息框

MB_RETRYCANCEL

不含图标、可改变按钮

重试信息框

MB_YESNO

不含图标、可改变按钮

是否信息框

MB_YESNOCANCEL

不含图标、可改变按钮

是否取消信息框

怎样在dbgrid中显示memo字段的内容?

首先用query或Table控件来连接dbgrid,
然后双击query/Table控件,右击,选择add   all   fields,选择定义为memo类型的字段,选择该字段的ongettext事件,在事件里写入以下程序:
Text = Trim(Sender->AsString);
DisplayText = true;

遍历选择的行:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
DBGrid1->SelectedRows->Refresh();
TDataSet *pDS = DBGrid1->DataSource->DataSet;
for (int i=0; i < DBGrid1->SelectedRows->Count; i++)
{
pDS->GotoBookmark((void *)DBGrid1->SelectedRows->Items[i].c_str());

//pDs->…
}
}

Text =  FloatToStr(RoundTo(Sender->AsFloat*10000,-2)/100)+’%';

 

如何通过程序实现DBGRID的多行选择

dbgrid1.options.multiselected:=true;

procedure   TForm1.BitBtn1Click(Sender:   TObject);
begin
with   dbgrid1.DataSource.DataSet   do
begin
first;
while   not   eof   do
begin
dbgrid1.SelectedRows.CurrentRowSelected:=true;
next;
end;
end;

dbgrid1.SetFocus;
end;

 

怎样判断数据库的记录是否被修改过

if(   tableDetail->State==dsEdit   ||   tableDetail->State==dsInsert   )
{
ShowMessage(“数据未保存”);
}

获取单元格正在编辑的值:

获取GetDBGridEditText(DBGridEdit)

TEdit *GetDBGridEdit(TDBGrid *mDBGrid)
{
for(int i=0; i<mDBGrid->ComponentCount; i++)
{
if(mDBGrid->Components[i]->InheritsFrom(__classid(TCustomEdit)))
return ((TEdit *)mDBGrid->Components[i]);
}
return NULL;
}

String GetDBGridEditText(TDBGrid *mDBGrid)
{
TEdit *vEdit = GetDBGridEdit(mDBGrid);
if(vEdit)
return vEdit->Text;
else
return “”;
}

 

InstallShield Express制作Delphi数据库安装程序

Delphi编写的数据库程序在发布时需要同时发布BDEBorland Database Engine),但BDE占用空间较大(不同版本大小不一,最新的Delphi517M多),远比一般的程序本身要大。但实际上,有些文件用不上的,所以我们可以在发布时用Delphi附带的InstallShield制作安装程序来定制BDE驱动,这样可以精简我们的数据库应用程序。
实现与应用
参考Bde32.HLP“Introduction to Borland Database Engine”下的“Core BDE Files”,可以得知BDE的关键文件及其作用,可以以此作为依据来精简BDE驱动程序。下面是各个文件的作用:
一、不可缺少的文件
Blw32.dll
:语言驱动函数库。
Idapi32.dll
BDE基本函数库。
Fareast.btl
Usa.btl:远东语言及美国语言驱动程序,对中文软件不可缺少。
Idr20009.dll
:错误信息库。 二、数据库驱动程序(根据需要选择一个或多个)
Idasci32.dll
Ascii文本数据库驱动程序函数库,如果不用Ascii文本数据库,可以不要。
Iddao32.dll
Access数据库驱动程序函数库,如果不用Access数据库,可以不要。
Iddbas32.dll
dBase数据库驱动程序函数库,如果不用dBase数据库,可以不要。
Idodbc32.dll
ODBC数据库驱动程序函数库,如果不用ODBC数据库,可以不要。
Idpdx32.dll
Paradox数据库驱动程序函数库,如果不用Paradox数据库,可以不要。 三、其它驱动程序和配置文件(根据需要选择一个或多个)
Idbat32.dll
:批操作驱动程序函数库,如果不用TBatchMove控件或DbiBatchMove类函数,可以不要。
Iddr32.dll
Data Repository驱动程序函数库,如果不用Data Repository功能,可以不要。
Idprov32.dll
BDE DataSet provider驱动程序函数库,如果不用TProvider控件,可以不要。
Idqbe32.dll
QBE驱动程序函数库,如果不用Query By Example,可以不要。
Idsql32.dll
SQL查询驱动程序函数库,如果不用TQuery进行查询,可以不要。
Idapi32.cfg
BDE配置文件,如果程序中没有特殊要求,可以不要。也可以在BDE管理器中设置正确后再分发。四、其它文件(一般不用)
其它的*.BTL:其它国家和地区的语言驱动程序,可以不要。
BDE32.HLP
BDE32.CNTBDE帮助文件,可以不要。
BdeAdmin.exe
BdeAdmin.HLPBdeAdmin.CNTBDE管理器及帮助文件,如果不会发生要求软件用户自己配置BDE的情况时,可以不要。
DataBump.EXE
DataBump.HLPDataBump.CNT:数据库数据转移工具及帮助文件,可以不要。
Localsql.HLP
Localsql.CNTSQL查询语句帮助文件,可以不要。
Sqllnk32.HLP
Sqllnk32.CNTSQL连接帮助文件,可以不要。在根据需要选择文件后,还要写注册表文件。可以手工设置,但最好在程序中设置,需要设置的注册表键值有(在调用数据库操作前需要有正确的键值存在,各对应键值在Win9x/NT/Win2000下均相同):
数据驱动程序所在目录的设置:
HKEY_LOCAL_MACHINE\Software\Borland\Database Engine\DLLPATH
(字符串值)
语言驱动程序所在目录的设置:
HKEY_LOCAL_MACHINE\Software \Borland\BLW32\BLAPIPATH
(字符串值)
语言驱动程序文件名:
HKEY_LOCAL_MACHINE\ Software\Borland\BLW32\LOCALE_LIB#
(字符串值) 其中#为编号,按顺序为0123……如:
HKEY_LOCAL_MACHINE\Software\Borland\BLW32\LOCALE_LIB0=”fareasst.btl”
HKEY_LOCAL_MACHINE\Software\Borland \BLW32\LOCALE_LIB1=”usa.btl”
做完这些就足够了,按此办法即可有效减少BDE驱动程序的大小,例如只用TTable控件操作Paradox数据库,则只要Idapi32.dllBlw32.dllIdr20009.dllFareast.btlUsa.btlIdpdx32.dll六个文件即可。这些文件可放在任何一个目录,只要在注册表指明即可。BDE17.4M减到1.48M,压缩一下就只有几百K了,这使程序大为减小。
下面我们就以用InstallShield来制作一个Paradox数据库应用系统的安装程序为例:
1.
启动程序设置有关文件目录路径,进入Setup Checklist
2.
Set the Visual Design中设置程序名、程序目录、安装程序主窗口等;
3.
Specify Components and Files中设置Groups and Files项,在Program Files中加入用户的所有程序文件和数据库表文件,以及下列文件:Idbat32.dllUsa.btlIdapi.cfgCharset.cvbBantam.dllBLW32.dllIdapi32.dllFareast.btlIdpdx32.dllIdr20009.dllIdsql32.dll(以上文件必须含目录路径);
4.
Dialog Boxes中设置所需安装对话框;
5.
Make Registry Changes中设置Keys项,在HKEY_LOCAL_MACHINE中加入software\borland\blw32software\borland\database engine两项,并且在blw32值中加入
“Blapipath ´
以上文件目录´”“LOCALE_LIB0 ´以上文件目录´\Fareast.bll”“LOCALE_LIB1 ´以上文件目录´\Usa.bll”,在database engine值中加入“Dllpath ´以上文件目录´”“Configfile01 ´以上文件目录´\Idapi.cfg”
6.
Specify Folder and Icons中根据实际要求设置有关项目;
7.
Run Disk Builder中设置安装盘的有关信息;
8.
最后进行Test the InstallationCreate Distribution Media即可完成安装程序的制作。

TRACKBACK:http://www.kpwang.com/delphi/1106517142543.htm

“Could not initialize BDE” error when trying to start Database Desktop

Abstract: “Could not initialize BDE” error when trying to start Database Desktop

“Could not initialize BDE” error when trying to start Database Desktop

  • Product Name:C++Builder
  • Product Version:All
  • Product Component:Database Desktop,BDE (Borland Database Engine)
  • Platform/OS Version: AllDescription:When I try to start Database Desktop, I get a “Could not initialize BDE” error, after which Database Desktop closes.I am also unable to start BDE Administrator — there are no error messages; it simply does not start when double-clicked.In addition, attempts to use the BDE from within the C++Builder IDE are met with a “An error occurred while attempting to initialize the Borland Database Engine (error $2108)” failure.Answer/Solution:This behavior strongly suggests a problem with your BDE path, which is stored in the following part of the Registry:HKEY_LOCAL_MACHINE | SOFTWARE | Borland | Database EngineIn that Registry key, the value CONFIGFILE01 needs to point to your idapi32.cfg file, and the value DLLPath needs to point to the directory where your idapi32.dll resides.If you have installed C++Builder and the BDE to the default directories, then the data for CONFIGFILE01 should be:C:\Program Files\Common Files\Borland Shared\BDE\IDAPI32.CFGAnd the data for DLLPath should be:C:\Program Files\Common Files\Borland Shared\BDEThe CONFIGFILE01 and DLLPath values may be added manually if they are missing. Their presence, assuming all else is intact, will solve the problem.Author: Yu-Chen Hsueh
  • 编程连接ODBC
  • void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    AnsiString   AccessDll;
    AnsiString   S;
    TRegistry   *Registry = new TRegistry;
    try
    {
    Registry->RootKey = HKEY_LOCAL_MACHINE;
  • if(Registry->OpenKey(“Software\\ODBC\\ODBCINST.INI\\ODBC   Drivers”,false))
    {
    S = Registry->ReadString(“Microsoft   Access   Driver   (*.mdb)”);
    if( S !=   AnsiString(“Installed”))
    {
    MessageBox(Application->Handle,”The system isn’t install the Access driver.”,” Warning”,MB_ICONWARNING);
    return;
    }
    else
    {
    MessageBox(Application->Handle,”This system have already installed the access driver.”,”Information”,MB_ICONINFORMATION);
    }
    }
    else
    {
    MessageBox(Application->Handle,”The Read odbcinst.ini\odbc driver error.”,”Warning”,MB_ICONWARNING);
    }
    Registry->CloseKey();
  • Registry->RootKey = HKEY_LOCAL_MACHINE;
    if(Registry->OpenKey(“Software\\ODBC\\ODBCINST.INI\Microsoft Access Driver(*.mdb)”,false))
    //if(Registry->OpenKey(“Software\\ODBC\\ODBCINST.INI\Driver do Microsoft Access (*.mdb)”,false))
    {
    AccessDll = Registry->ReadString(“Driver”);
    }
    else
    {
    MessageBox(Application->Handle,”Read the ODBC\ODBCINST.INI\Microsoft AccessDriver Error.”,”Warning.”,MB_ICONWARNING);
    }
  • Registry->CloseKey();
    Registry->RootKey = HKEY_CURRENT_USER;
    if(Registry->OpenKey(“Software\\ODBC\\ODBC.INI\\ODBC Data Sources”,TRUE))
    {
    Registry->WriteString(“myAccessDealerLinker”,”Microsoft Access Driver (*.mdb)”);//”Driver do Microsoft Access(*.mdb)”);
    //Registry->WriteString(“myAccessDealerLinker”,”Driver do Microsoft Access (*.mdb)”);//”Driver do Microsoft Access(*.mdb)”);
    AnsiString s;
    s = Registry->ReadString(“MyAccessDSN”);
    }
    else
    {
    ShowMessage(“Create the MyAccess  Error”);
    }
  • Registry->CloseKey();
    Registry->RootKey = HKEY_CURRENT_USER;
    if(Registry->OpenKey(“Software\\ODBC\\ODBC.INI\\myAccessDealerLinker”,TRUE))
    {
    Registry->WriteString(“DBQ”,”C:\\BCB Project\\Dealers\\DATA\\myData.mdb”);
    Registry->WriteString(“Drscription”,”");
    Registry->WriteString(“Driver”,”C:\\WINDOWS\\system32\\odbcjt32.dll”);
    Registry->WriteInteger(“DriverId”,0×00000019);
    Registry->WriteString(“FIL”,”MS Access;”);
    Registry->WriteString(“PWD”,”BOS8251617″);
    Registry->WriteInteger(“SafeTransactions”,0×00000000);
    Registry->WriteString(“UID”,”");
  • if(Registry->OpenKey(“Engines\\Jet”,TRUE))
    {
    Registry->WriteString(“ImplicitCommitSync”,”");
    Registry->WriteInteger(“MaxBufferSize”,0×00000800);
    Registry->WriteInteger(“PageTimeout”,0×00000005);
    Registry->WriteInteger(“Threads”,0×0000003);
    Registry->WriteString(“UserCommitSync”,”no”);
    }
    else
    {
    ShowMessage(“Safeware\ODBC\MyAccessDSNtest\Engines\Jet Error”);
    }
    }
    else
    {
    ShowMessage(“Create the data source  error.”);
    }
    }
    __finally
    {
    delete   Registry;
    }
    }
  • 判断windowsDesktop及其它目录  使用API函数SHGetSpecialFoldershlobj.h里有SHGetSpecialFolder的原型声明。这个函数可以帮我们找到windowsDesktop目录、启动目录、我的文档目录等。 SHGetSpecialFolder需要三个参数。 第一个参数是HWND,它指定了所有者窗口:在调用这个函数时可能出现的对话框或消息框。第二个参数是一个整数id,决定哪个目录是待查找目录,它的取值可能是:

    • CSIDL_BITBUCKET 回收站
    • CSIDL_CONTROLS 控制面板
    • CSIDL_DESKTOP Windows 桌面desktop
    • CSIDL_DESKTOPDIRECTORY desktop的目录
    • CSIDL_DRIVES 我的电脑
    • CSIDL_FONTS 字体目录
    • CSIDL_NETHOOD 网上邻居
    • CSIDL_NETWORK 网上邻居virtual folder
    • CSIDL_PERSONAL 我的文档
    • CSIDL_PRINTERS 打印机
    • CSIDL_PROGRAMS 程序组
    • CSIDL_RECENT 大多数最近打开的文档列一
    • CSIDL_SENDTO “发送到菜单项
    • CSIDL_STARTMENU 任务条启动菜单项
    • CSIDL_STARTUP 启动目录
    • CSIDL_TEMPLATES 临时文档

    最后一个参数是pidl地址。SHGetSpecialFolderLocation把地址写到pidl 下面的代码演示了怎样使用SHGetSpecialFolderLocation

    //——————————————————————— #define NO_WIN32_LEAN_AND_MEAN// add First sentence #include <ShlObj.hpp> void __fastcall TForm1::Button1Click(TObject *Sender) { LPITEMIDLIST pidl; LPMALLOC pShellMalloc; char szDir[MAX_PATH]; if(SUCCEEDED(SHGetMalloc(&pShellMalloc))) { if(SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &pidl))) { // 如果成功返回true if(SHGetPathFromIDList(pidl, szDir)) { Label1->Caption = szDir; } pShellMalloc->Free(pidl); } pShellMalloc->Release(); } } //———————————————————————-

     

    RE: Rave Reports: Sending to a specific printer
      This is from the FAQ part of the RaveDevGuide…QUESTION:
    How do I change the active printer when I am doing a report?ANSWER:
    To programmatically change the printer in a code based report do the following:
    1) Place “RpDevice” in your Uses clause2) Get the desired printer name, for example:
    RpDev.PrinterSetupDialog;
    sPrinterName := RpDev.Device;
    save this in INI etc for later use in your program3) Set the printer with
    RpDev.SelectPrinter( sPrinterName, False );The second parameter indicates whether you need an exact match or not on the printer name.See if that works.George

    如何在BCB里将按ENTER键切换输入框的焦点

    我是这样处理的:
    void   __fastcall   TForm1::FormKeyPress(TObject   *Sender,   char   &Key)
    {
    if(Key==VK_RETURN)
    {
    SendMessage(this->Handle,WM_NEXTDLGCTL,0,0);
    Key=0;
    }
    }
    没有报警声,须将FORM的KeyPreview设置=TRUE

    #include   “DateUtils.hpp”
    TDateTime   dt1,   dt2;
    int   iDays;
    dt1   =   TDateTime(“2005-08-03   00:00:00″);
    //   以下是加3天,以此类推,减3天就是IncDay(dt1,   -3)
    dt2   =   IncDay(dt1,   3);
    Memo1->Lines->Add(DateTimeToStr(dt2));   //   2005-08-06
    //   以下是求两日期相差的天数
    iDays   =   DaysBetween(dt1,   dt2);
    Memo1->Lines->Add(IntToStr(iDays));   //   3

    ClientDataSet中的数据如何排序?

     

    ClientDataSet.IndexFieldNames=列名
    这样可以实现排序——升序 , 但我要实现降序如何解决???

     

    创建一个IndexDef,在Option选择ixDescending,然后设定TClientDatasetIndexName就可以了。

     

     

    ClientDataSet使用心得和技巧
    http://blog.sina.com.cn/s/blog_59cb8a930100aw4v.html

     

     

    影响ClientDataSet处理速度的一个因素
    TClientDataSet
    Delphi开发数据库时一个非常好的控件。有很强大的功能。
    我常常用ClientDataSetMemoryDataSet来使用。还可以将ClientDataSet的数据保存为XML,这样就可以做简单的本地数据库使用。还有很多功能就不多说了。在使用ClientDataSet的过程中关于怎样提高处理速度这个问题,我就我个人的一点点体会和大家分享一下。

    通常情况下我们一般都是用
    …ClientDataSet–>DataSource–>DBComponent
    这样的结构,处理数据的时候就直接操作ClientDataSet。但是大多DBComponet都会立即响应ClientDataSet的变化。如果你是向ClientDataSet中插入很多数据时候,DBComponent就要响应几次,而且响应过程根据不同的控件,速度,过程数量都不一样。这样就影响了程序的执行效率。所以在对ClientDataSet处理中,我是用ClientDataSet.DisableControlsClientDataSet.EnableControls方法:打开和关闭DBComponentClientDataSet的数据显示关系。
    例如:
    ClientDataSet..DisableControls;

    for I := 0 to 10000 do
    begin
    ClientDataSet.Append;

    ClientDataSet.Post;
    end;

    ClientDataSet.EnableControls

    这样做以后你会发现处理速度比以前没有使用方法的时候有成倍的提高。

    ClientDataSet的数据查找。
    我所介绍的心得和技巧都是用ClientDataSet来做范例,也可以应用于其他的一些DataSet。废话就不多说了。我们还是先看代码,让后再总结。
    1.Scanning
    扫描数据查找
    这是最简单最直接也是最慢的一种方法,遍历所有数据:

     

    procedure TForm1.ScanBtnClick(Sender: TObject);
    var
    Found: Boolean;
    begin
    Found := False;
    ClientDataSet1.DisableControls;
    Start;
    try
    ClientDataSet1.First;
    while not ClientDataSet1.Eof do
    begin
    if ClientDataSet1.Fields[FieldListComboBox.ItemIndex].value =
    SearchText then
    begin
    Found := True;
    Break;
    end;
    ClientDataSet1.Next;
    end;
    Done;
    finally
    ClientDataSet1.EnableControls;
    end;
    if Found then ShowMessage(SearchText +
    ‘ found at record ’ + IntToStr(ClientDataSet1.RecNo))
    else
    ShowMessage(ScanForEdit.Text + ’ not found’);
    end;

     

    2.Finding 寻找数据
    最老,但是最快的查找方式。
    使用FindKey/FindNearest来查找一条或多条符合条件的数据,当然待查找的Field必须是一个IndexField。可以看出,这种基于Index的查找速度是非常快的。

     

    procedure TForm1.FindKeyBtnClick(Sender: TObject);
    begin
    Start;
    if ClientDataSet1.FindKey([SearchText]) then
    begin
    Done;
    StatusBar1.Panels[3].Text := SearchText +
    ‘ found at record ’ +
    IntToStr(ClientDataSet1.RecNo);
    end
    else
    begin
    Done;
    StatusBar1.Panels[3].Text :=
    SearchText + ’ not found’;
    end;
    end;

    procedure TForm1.FindNearestBtnClick(Sender: TObject);
    begin
    Start;
    ClientDataSet1.FindNearest([SearchText]);
    Done;
    StatusBar1.Panels[3].Text := ’The nearest match to ’ +
    SearchText + ’ found at record ’ +
    IntToStr(ClientDataSet1.RecNo);
    end

     

    3.Going 定位
    GotoKey/GotoNearest
    FindKey/FindNearest基本上没有什么区别。它也是基于Index的查找。唯一的区别就是在于你是怎么定义你的查找了。代码上也有区别:
    ClientDataSet1.SetKey;
    ClientDataSet1.FieldByName(IndexFieldName).value := SearchText;
    ClientDataSet1.GotoKey;
    就相当于
    ClientDataSet1.FindKey([SearchText]);
    要用好这两种基于Index的查找,还需要了解ClientDataSetIndex机制。这里就不详细说明Index机制。一个基本的原则,要有Index,才能查找。


    4.Locating
    查找数据
    2,3
    两种查找方式都是基于Index的,但是在实际应用中,可能会查找IndexField以外的Field。那我们就可以使用Locate。但是查找速度是没有2,3两种快的。比如:如果你查找一条纪录9000/10000Locate需要500msScanning需要>2sFindKey只要10ms(但是当你打开ClientData的时候,建立Index需要1s)。

    procedure TForm1.LocateBtnClick(Sender: TObject);
    begin
    Start;
    if ClientDataSet1.Locate(‘Field1,Field2..’,VarArrayOf['value1,value2..'], []) then
    begin
    Done;
    StatusBar1.Panels[3].Text :=
    ‘Match located at record ’ +
    IntToStr(ClientDataSet1.RecNo);
    end
    else
    begin
    Done;
    StatusBar1.Panels[3].Text := ’No match located’;
    end;
    end;


    ClientDataSet
    提供了好多种查找数据的方法。但是各自有其优缺点。
    上面的例子中有Start;Done,如果你有兴趣,可以加入计时点进行速度测试。
    Scanning
    最简单,但是最慢,因为比较慢,还得使用ClientDataSet.DisableControlsClientDataSet.EnableControls方法(我在前面一片文章讲过)
    Findkey/FindNearest(GotoKey/GotoNearest)
    代码多,但是非常快。必须使用Index,不同的是Find需要的Index是必须建立好的,而Goto可以在第一次使用时建立Index
    Locate
    使用最方便,不需要Index,但是速度没有Find快。

    点击此处查看原文

    评论 (0)| 阅读 (7) | 收藏 (0) | 分享 | 举报

    DELPHI 数据库控件心得(1) (2008-10-27 00:29)

    标签:杂谈

    分类:Delphi

    TField对象的SetTextGetText事件处理函数

    使用TField对象的SetTextGetText事件处理函数可方便的解决字段的代码与代码所对应值的显示问题


    TSimpleDataset/TClientDataset
    对象的Aggregation

    使用TDataset对象的Aggregate属性可以来计算客户端数据集中数据的总计数值、平均值或是计算最大值和最小值。


    使用TBookMark来标记记录书签, 访问数据集中的数据

    通过使用TBookMark以及TDataset对象的 BookMark 属性, 要以为当前的纪录设置书签,

    var
    bk:TBookMark;
    begin
    bk:=ds.GetBookMark; //
    设置书签
    ….
    ds.GoToBookMark(bk);//
    回到原来的纪录
    ds.FreeBookMark(bk);//
    释放内存
    end;

     

    Locate Lookup 区别:

    Locate找到查寻的数据后,它会把目前的记录位置移动到找到的这笔数据上
    Lookup
    找到查寻的数据后,它会回传找到的数据的特定字段数值,却不会移动目前的记录位置。

    Lookup方法的第三个参数则是指定当Lookup找到欲查寻的数据之后,要回传这笔数据的那些字段数值。如果开发人员想要Lookup回传多个字段数值,那么每一个字段也是以分号分隔。

    至于Lookup方法回传的数值则是第三个字段指定的字段数值,如果Lookup回传多个字段的话,那么这个回传数值就是一个Variant数组,每一个回传的字段便储存在这个Variant数组的元素之中。

    :

     

     

    var
    sFields : String;
    vResult : Variant;
    iCount : Integer;
    begin
    vResult := ds.Lookup(‘fieldnameA, fieldnameB’ , VarArrayCreate([ValueA, ValueB], varVariant), ’fieldname1, fieldname2′);
    if (VarIsArray(vResult)) then
    begin
    sFields := ”;
    for iCount := VarArrayLowBound(vResult, 1) to VarArrayHighBound(vResult,  1) do
    begin
    sFields := sFields + ’;' + vResult[iCount];
    end;
    end
    else
    edtReturn.Text := vResult;
    end;

     

    一些使用 DevExpress 时的小心得
    1. 设置 DataController.Filter.AutoDataSetFilter=True 可以使过滤器直接影响后台数据集。
    2.
    关于cxFormatController的一些用法。当修改了系统默认数据格式定义时,cxFormatController可通过方法 GetFormats NotifyListeners 来实现刷新。
    例:
    CurrencyString := ‘
    ‘;
    SysUtils.CurrencyFormat := 3;
    SysUtils.CurrencyDecimals := 4;
    cxFormatController.GetFormats;
    cxFormatController.NotifyListeners;
    3.
    更新当前所选行中某列的值,可以按以下方法实现,

    Column.EditValue := AValue
    。如可使用 Record.Values[AIndex] := AValue,并不能直接更新行中指定值所对应的数据集中的值。通过 Column.EditValue 刚可以实现。
    TDatasetProvider.UpdateMode属性;
    upWhereAll
    限制最严,但可以最大程度地保证记录的一致性。如果两个用户编辑同一条记录,第一个用户能够更新记录,而第二个用户将会收到“另一个用户已经修改了这条记录”的报错信息。如果希望改进执行这种检查的字段,可以去掉相应的TField.ProviderFlags属性中的pfInWhere项。
    upWhereChanged 实际上允许两个用户同时编辑一条记录;在两个用户编辑同一条记录的不同字段时,不会检查出冲突。例如,如果用户A修改Address字段并更新了记录,那么用户B仍然能够修改BirthDate字段并成功地更新记录。
    upWhereKeyOnly 限制最宽。只要是记录存在于数据库中,每个用户都可以进行修改并更新。这样,后面的修改总是覆盖前面的修改。
    系统默认的是upWhereAll,请修改为你认为合适的模式!
    ADO 中处理多个返回结果集
    在使用 SQL 语句时,常常会有多个结果集被返回的情况,比如 EXEC sp_helpconstraint [TableName] 就返回了两个结果集。如果我们需要处理多个结果集时。可用ADO NextRecordSet 方法。用法如下:

     

    var
    R: integer
    begin
    with ADOQuery do
    begin
    Close;
    SQL.Text := ’EXEC sp_helpconstraint ’ + ableName;
    Open;
    R := 0;
    Recordset := NextRecordSet(R);
    {do something }

    end

     

    TField对象的SetText和GetText事件处理函数

    使用TField对象的SetText和GetText事件处理函数可方便的解决字段的代码与代码所对应值的显示问题


    TSimpleDataset/TClientDataset对象的Aggregation

    使用TDataset对象的Aggregate属性可以来计算客户端数据集中数据的总计数值、平均值或是计算最大值和最小值。


    使用TBookMark来标记记录书签, 访问数据集中的数据

    通过使用TBookMark以及TDataset对象的 BookMark 属性, 要以为当前的纪录设置书签,

    var
    bk:TBookMark;
    begin
    bk:=ds.GetBookMark; //设置书签
    ….
    ds.GoToBookMark(bk);//回到原来的纪录
    ds.FreeBookMark(bk);//释放内存
    end;

     

    Locate 与 Lookup 区别:

    Locate找到查寻的数据后,它会把目前的记录位置移动到找到的这笔数据上
    Lookup找到查寻的数据后,它会回传找到的数据的特定字段数值,却不会移动目前的记录位置。

    Lookup方法的第三个参数则是指定当Lookup找到欲查寻的数据之后,要回传这笔数据的那些字段数值。如果开发人员想要Lookup回传多个字段数值,那么每一个字段也是以分号分隔。

    至于Lookup方法回传的数值则是第三个字段指定的字段数值,如果Lookup回传多个字段的话,那么这个回传数值就是一个Variant数组,每一个回传的字段便储存在这个Variant数组的元素之中。

    例:

     

     

    var
    sFields : String;
    vResult : Variant;
    iCount : Integer;
    begin
    vResult := ds.Lookup(
    ‘fieldnameA, fieldnameB’ , VarArrayCreate([ValueA, ValueB], varVariant), ‘fieldname1, fieldname2′);
    if (VarIsArray(vResult)) then
    begin
    sFields :=
    ;
    for iCount := VarArrayLowBound(vResult, 1) to VarArrayHighBound(vResult, 1) do
    begin
    sFields := sFields +
    ‘;’ + vResult[iCount];
    end;
    end
    else
    edtReturn.Text := vResult;
    end

    ;

     

     

    一些使用 DevExpress 时的小心得
    1. 设置 DataController.Filter.AutoDataSetFilter=True 可以使过滤器直接影响后台数据集。
    2. 关于cxFormatController的一些用法。当修改了系统默认数据格式定义时,cxFormatController可通过方法 GetFormats 与 NotifyListeners 来实现刷新。
    例:
    CurrencyString := ‘元’;
    SysUtils.CurrencyFormat := 3;
    SysUtils.CurrencyDecimals := 4;
    cxFormatController.GetFormats;
    cxFormatController.NotifyListeners;
    3.更新当前所选行中某列的值,可以按以下方法实现,
    Column.EditValue := AValue。如可使用 Record.Values[AIndex] := AValue,并不能直接更新行中指定值所对应的数据集中的值。通过 Column.EditValue 刚可以实现。
    TDatasetProvider.UpdateMode属性;
    upWhereAll   限制最严,但可以最大程度地保证记录的一致性。如果两个用户编辑同一条记录,第一个用户能够更新记录,而第二个用户将会收到“另一个用户已经修改了这条记录”的报错信息。如果希望改进执行这种检查的字段,可以去掉相应的TField.ProviderFlags属性中的pfInWhere项。
    upWhereChanged   实际上允许两个用户同时编辑一条记录;在两个用户编辑同一条记录的不同字段时,不会检查出冲突。例如,如果用户A修改Address字段并更新了记录,那么用户B仍然能够修改BirthDate字段并成功地更新记录。

    upWhereKeyOnly   限制最宽。只要是记录存在于数据库中,每个用户都可以进行修改并更新。这样,后面的修改总是覆盖前面的修改。
    系统默认的是upWhereAll,请修改为你认为合适的模式!

    ADO 中处理多个返回结果集
    在使用 SQL 语句时,常常会有多个结果集被返回的情况,比如 EXEC sp_helpconstraint [TableName] 就返回了两个结果集。如果我们需要处理多个结果集时。可用ADO的 NextRecordSet 方法。用法如下:

    var
    R: integer
    begin
    with ADOQuery do
    begin
    Close;
    SQL.Text :=
    ‘EXEC sp_helpconstraint ’ + ableName;
    Open;
    R :=
    0;
    Recordset := NextRecordSet(R);
    {do something }

    end

     

     

     

     

     

     

     

    =============================================================

     
     
     
     

    BCB提供的文件操作函数
    2008年03月21日 20:56

    在BCB中也提供了文件操作的函数,这些函数的功能和前面所介绍的大致相同,但这类函数和BCB关系紧密,能使用BCB中的AnsiString等数据类型,在BCB中用这种方式的文件操作是最方便的,下面我就把这种文件操作详细介绍。

    在BCB提供的这组文件操作函数中,可分为三种类型,就是:1、文件名函数,2、文件管理函数;3、文件I/O函数。

    1. 文件名函数

    文件名函数可以对文件的名称、所在子目录、驱动器和扩展名等进行操作。下表列出这些函数及其功能。

    函数 说明

    ExpandFileName() 返回文件的全路径(含驱动器、路径)

    ExtractFileExt() 从文件名中抽取扩展名

    ExtractFileName() 从文件名中抽取不含路径的文件名

    ExtractFilePath() 从文件名中抽取路径名

    ExtractFileDir() 从文件名中抽取目录名

    ExtractFileDrive() 从文件名中抽取驱动器名

    ChangeFileExt() 改变文件的扩展名

    ExpandUNCFileName() 返回含有网络驱动器的文件全路径

    ExtractRelativePath() 从文件名中抽取相对路径信息

    ExtractShortPathName() 把文件名转化为DOS的8·3格式

    MatchesMask() 检查文件是否与指定的文件名格式匹配

    下面就把这些函数作一一介绍:

    ⑴ExpandFileName()

    原型:extern PACKAGE AnsiString __fastcall ExpandFileName(const AnsiString FileName);

    功能:返回文件的全路径(含驱动器、路径)

    参数:FileName:要处理的文件名

    例:ShowMessage(ExpandFileName(Application->ExeName));//显示你的程序文件名,如C:\MyBCB\Sample1.EXE

    ⑵ExtractFileExt()

    原型:extern PACKAGE AnsiString __fastcall ExtractFileExt(const AnsiString FileName);

    功能:从文件名中抽取扩展名

    参数:FileName:要处理的文件名(全路径)

    例:ShowMessage(ExtractFileExt(Application->ExeName));//显示”.exe”

    ⑶ExtractFileName()

    原型:extern PACKAGE AnsiString __fastcall ExtractFileName(const AnsiString FileName);

    功能:从文件名中抽取不含路径的文件名

    参数:FileName:要处理的文件名

    例:ShowMessage(ExtractFileExt(“c:\\Winnt\\SOL.EXE”));//显示”SOL.EXE”

    ⑷ExtractFilePath()

    原型:extern PACKAGE AnsiString __fastcall ExtractFilePath(const AnsiString FileName);

    功能:从文件名中抽取路径名

    参数:FileName:要处理的文件名

    例:ShowMessage(ExtractFilePath(“Winnt\\SOL.EXE”));//显示”Winnt\”

    ⑸ExtractFileDir()

    原型:extern PACKAGE AnsiString __fastcall ExtractFileDir(const AnsiString FileName);

    功能:从文件名中抽取目录名(和上个函数不同,不包括最后的”\”)

    参数:FileName:要处理的文件名

    例:ShowMessage(ExtractFileDir(“Winnt\\SOL.EXE”));//显示”Winnt”,注意和上个函数的区别

    ⑹ExtractFileDrive()

    原型:extern PACKAGE AnsiString __fastcall ExtractFileDrive(const AnsiString FileName);

    功能:从文件名中抽取驱动器名

    参数:FileName:要处理的文件名

    例:ShowMessage(ExtractFileDrive(“c:\\Winnt\\SOL.EXE”));//显示”c:”

    ⑺ChangeFileExt()

    原型:extern PACKAGE System::AnsiString __fastcall ChangeFileExt(const System::AnsiString FileName, const System::AnsiString Extension);

    功能:更改文件名的扩展名,不是对真正的文件进行改名,只是对文件名这个字符串进行处理

    参数:FileName:要改名的文件名,Extension:新的扩展名

    例:ShowMessage(ChangeFileExt(“c:\\Winnt\\SOL.EXE”,”.OOO”));//显示”c:\winnt\SOL.OOO”

    ⑻ExpandUNCFileName()

    原型:extern PACKAGE AnsiString __fastcall ExpandUNCFileName(const AnsiString FileName);

    功能:返回含有网络驱动器的文件全路径,格式为:\\机器名\共享名\文件名

    参数:FileName:要处理的文件名

    例:ShowMessage(ExpandUNCFileName(“F:\\Winnt\\SOL.EXE”));/*如果F:是映射的网络驱动器\\NT40\WINNT,则显示”\\NT40\WINNT\SOL.EXE”*/

    ⑼ExtractRelativePath()

    原型:extern PACKAGE AnsiString __fastcall ExtractRelativePath(const AnsiString BaseName, const AnsiString DestName);

    功能:从文件名中抽取相对路径信息,如”..\sss\ss.asd”这种形式

    参数:BaseName:基准文件名;DestName:目标文件名

    例:ShowMessage(ExtractRelativePath(“D:\\Source\\c\\1.123″,”D:\\Source\\Asm\\dz.asm”));/*显示”..\asm\dz.asm”*/

    ⑽ExtractShortPathName()

    原型:extern PACKAGE AnsiString __fastcall ExtractShortPathName(const AnsiString FileName);

    功能:把文件名转换为DOS的8、3格式

    参数:FileName:要处理的文件名

    例:ShowMessage(ExtractShortPathName(“E:\\Program Files\\Dual Wheel Mouse\\4dmain.exe”));/*显示”E:\Progra~1\dualwh~1\4dmain.exe”*/

    ⑾MatchesMask()

    原型:extern PACKAGE bool __fastcall MatchesMask(const AnsiString Filename, const AnsiString Mask);

    功能:检查文件是否与指定的文件名格式匹配

    参数:FileName:要处理的文件名;Mask:文件名格式,支持通配符

    例:ShowMessage(MatchesMask(“Lxf.exe”,”*.?x?));//显示”true”

    2. 文件管理函数

    这类函数包括设置和读取驱动器、子目录和文件的有关的各种操作,下表列出这类操作常用的函数及其功能。

    函数 功能

    CreateDir() 创建新的子目录

    DeleteFile() 删除文件

    DirectoryExists() 判断目录是否存在

    DiskFree() 获取磁盘剩余空间

    DiskSize() 获取磁盘容量

    FileExists() 判断文件是否存在

    FileGetAttr() 获取文件属性

    FileGetDate() 获取文件日期

    GetCurrentDir() 获取当前目录

    RemoveDir() 删除目录

    SetCurrentDir() 设置当前目录

    ⑴CreateDir()

    原型:extern PACKAGE bool __fastcall CreateDir(const System::AnsiString Dir);

    功能:建立子目录,如果成功返回true,否则返回false

    参数:Dir:要建立的子目录的名字

    例:Create(“ASM”);//在当前目录下建立一个名为ASM的子目录

    ⑵DeleteFile()

    原型:extern PACKAGE bool __fastcall DeleteFile(const System::AnsiString FileName);

    功能:删除文件,如果成功返回true,否则返回false

    参数:FileName:要删除的文件名

    例:if(OpenDialog1->Execute())DeleteFile(OpenDialog1->FileName);

    ⑶DirectoryExists()

    原型:extern PACKAGE bool __fastcall DirectoryExists(const System:: AnsiString Name);

    功能:检测目录是否存在,如果存在返回true,否则返回false

    参数:Name:要检测的目录名

    例:if(!DirectoryExists(“ASM”))CreateDir(“ASM”);//如果ASM这个目录不存在则创建之

    ⑷DiskFree()

    原型:extern PACKAGE __int64 __fastcall DiskFree(Byte Drive);

    功能:检测磁盘剩余空间,返回值以字节为单位,如果指定的磁盘无效,返回-1

    参数:Drive:磁盘的代号,0表示当前盘, 1=A,2=B,3=C 以此类推

    例:ShowMessage(DiskFree(0));//显示当前盘的剩余空间

    ⑸DiskSize()

    原型:extern PACKAGE __int64 __fastcall DiskSize(Byte Drive);

    功能:检测磁盘容量,返回值以字节为单位,如果指定的磁盘无效,返回-1

    参数:Drive:磁盘的代号,0表示当前盘, 1=A,2=B,3=C 以此类推

    例:ShowMessage(DiskFree(0));//显示当前盘的容量

    ⑹FileExists()

    原型:extern PACKAGE bool __fastcall FileExists(const AnsiString FileName);

    功能:检测文件是否存在,如果存在返回true,否则返回false

    参数:FileName:要检测的文件名

    例:if(FileExists(“AAA.ASM”))DeleteFile(“AAA.ASM”);

    ⑺FileGetAttr()

    原型:extern PACKAGE int __fastcall FileGetAttr(const AnsiString FileName);

    功能:取得文件属性,如果出错返回-1

    返回值如下表,如果返回$00000006表示是一个具有隐含和系统属性的文件(4+2)

    常量 值 含义

    faReadOnly $00000001 只读文件

    faHidden $00000002 隐含文件

    faSysFile $00000004 系统文件

    faVolumeID $00000008 卷标

    faDirectory $00000010 目录

    faArchive $00000020 归档文件

    例:if(FileGetAttr(“LLL.TXT”)&0×2)ShowMessage(“这是一个有隐含属性的文件”);

    与此对应的有FileSetAttr() ,请自已查阅帮助系统

    ⑻FileGetDate()

    原型:extern PACKAGE int __fastcall FileGetDate(int Handle);

    功能:返回文件的建立时间到1970-1-1日0时的秒数

    参数:Handle:用FileOpen()打开的文件句柄。

    例:

    int i=FileOpen(“C:\\autoexec.bat”,fmOpenRead);

    ShowMessage(FileGetDate(i));

    FileClose(i);

    与此对应的有FileSetDate(),请自已查阅帮助系统

    ⑼GetCurrentDir()

    原型:extern PACKAGE AnsiString __fastcall GetCurrentDir();

    功能:取得当前的目录名

    例:ShowMessage(GetCurrentDir());

    ⑽RemoveDir()

    原型:extern PACKAGE bool __fastcall RemoveDir(const AnsiString Dir);

    功能:删除目录,如果成功返回true,否则返回false

    参数:Dir:要删除的目录名

    例:if(DiectoryExists(“ASM”))RemoveDir(“ASM”);

    ⑾SetCurrentDir()

    原型:extern PACKAGE bool __fastcall SetCurrentDir(const AnsiString Dir);

    功能:设置当前目录,如果成功返回true,否则返回false

    参数:Dir:要切换到的目录名

    例:SetCurrentDir(“C:\\WINDOWS”);

    3. 文件I/O函数

    这类函数完成对文件的读写相关的操作,这种类型的操作和C的基于I/O文件操作类似,下表列出这类操作常用的函数及其功能。

    FileOpen() 打开文件

    FileClose() 关闭文件

    FileRead() 读文件

    FileSeek() 文件定位

    FileWrite() 写文件

    FileCreate() 创建文件

    下面就对这些函数作详细介绍。

    ⑴FileOpen()

    原型:extern PACKAGE int __fastcall FileOpen(const AnsiString FileName, int Mode);

    功能:打开文件,如果成功返回其句柄,否则返回-1

    参数:FileName:要打开的文件名;Mode:打开的方式,取值如下表,可用”或”(“|”)运算符连接。

    常量 值 说明

    fmOpenRead 0 以只读属性打开

    fmOpenWrite 1 以只写属性打开

    fmOpenReadWrite 2 以读/写属性打开

    fmShareCompat 0 兼容FCB方式(汇编中有相应的DOS功能调用,感兴趣自已查阅相关资料)

    fmShareExclusive 16 共享方式:以独占方式打开,在关闭以前,别人不能访问

    fmShareDenyWrite 32 共享方式:拒绝写访问

    fmShareDenyRead 48 共享方式:拒绝读访问

    fmShareDenyNone 64 共享方式:无限制,允许读写

    例:int i=FileOpen(“C:\\WINDOWS\\Win.ini”,fmOpenReadWrite|fmShareExclusive);

    ⑵FileClose()

    原型:extern PACKAGE void __fastcall FileClose(int Handle);

    功能:关闭打开的句柄。

    参数:Handle:要关闭的句柄

    例:FileClose(i);

    ⑶FileRead()

    原型:extern PACKAGE int __fastcall FileRead(int Handle, void *Buffer, int Count);

    功能:读文件,返回实际读取的字节数,句柄必须首先由FileOpen或FileCreate创建。

    参数:Handle:要读取的句柄;Buffer:存放读取的数据的缓冲区;Count:想读取的字节数

    例:char str[400];FileRead(hnd1,str,400);

    ⑷FileSeek()

    原型:extern PACKAGE int __fastcall FileSeek(int Handle, int Offset, int Origin);

    功能:移动文件读取指针,成功返回文件指针的位置,失败返回-1

    参数:Handle:相关联的句柄;Offset:移动的量;Orgin:移动的基准,0=文件头,1=当前位置,2=文件尾。

    例:ShowMessage(FileSeek(hnd1,0,2));//取得文件的长度

    ⑸FileWrite()

    原型:extern PACKAGE int __fastcall FileWrite(int Handle, const void *Buffer, int Count);

    功能:写文件,返回实际写入的字节数,句柄必须首先由FileOpen或FileCreate创建。

    参数:Handle:要写入的句柄;Buffer:存放写入数据的缓冲区;Count:想写入的字节数

    例:char str[]=”I Love You”;FileWrite(hnd1,str,strlen(str));

    ⑹FileCreate()

    原型:extern PACKAGE int __fastcall FileCreate(const AnsiString FileName);

    功能:创建文件。成功返回其句柄,否则返回-1

    参数:FileName:要创建的文件名

    例:if(!FileExists(“KC.C”))hnd1=FileCreate(“KC.C”);

    取打印机名字

    void   __fastcall   TForm1::Button1Click(TObject   *Sender)
    {
    TPrinter   *Prntr   =   Printer();
    for(int   i=0;i<Prntr->Printers->Count;i++)
    {
    ListBox1->Items->Add(Prntr->Printers->Strings[i]);
    }
    }

     

    dbgrid里怎么让每一行根据不同的条件显示不同的颜色?

    void   __fastcall   TForm1::DBGrid1DrawColumnCell(TObject   *Sender,
    const   TRect   &Rect,   int   DataCol,   TColumn   *Column,
    TGridDrawState   State)
    {
    if   (((TDBGrid*)Sender)->DataSource->DataSet->RecNo   %   2   ==   0)   {
    ((TDBGrid*)Sender)->Canvas->Brush->Color   =   clBlue;
    DBGrid1->DefaultDrawColumnCell(Rect,   DataCol,   Column,   State);
    }
    }

    BCB中用Sender参数实现代码重用(修正版)
     
     
    面向对象的编程工具的特点之一就是要提高代码重用性(Reuse),宝兰的BCB当然可以实现这一功能。我们都知道,在BCB中,大部分程序代码都直接或间接的对应着一个事件,此程序称为事件处理句柄,它实际上就是一个过程。从应用程序的工程到窗口、组件和程序,BCB强调的是其开发过程中每一层次的重用性,可以充分利用已编写过的代码来减少工作量,更会使你的程序变得优美。代码段间的共享都跟发生该事件的控件有关有关,需要根据控件类型做出相应的处理,这时就要用到Sender参数。

    每个函数的开头都有形如:

    void _fastcall TForm1::Button1Click(TObject *Sender)

    其中的Sender是一个TObject类型的参数,它告诉BCB哪个控件接收到这个事件并调用相应的处理过程。我们可以编写一个单一的事件处理句柄,通过Sender参数和if语句或者case语句配合,来处理多个组件。在Delphi中可以用IS来测试Sender类型,或者用AS进行类型转换,BCB我们只在用dynamic_cast来进行上面两个工作,下面把dynamic_cast的用法说明一下。

    dynamic_cast 可以把某种对象强制转成另一个类,这里所谓的强制仍有其局限,也就是说,如果类转不过来,那么系统将不会进行转换操作的。若类型转换无法成功则返回一个值是0的指针。若参数T是一个参考类型,而类的转换又失败了,系统将会丢出一个异常处理信息:Bad_cast。但你放心这不会导致系统死机,所以可以放心使用。其程式:

    dynamic_cast <T> (ptr)

    T参数一定要是一个指针、void* 、或是已经定义过的类,而ptr参数则必须是一个指针(pointer) 或是一个引用(reference)。如果T的类型是void*,那么ptr则是一个可以访问最下面类里的任何成员,当然这样的类将不可以是基础类。

    1.进行判断

    我们用dynamic_case来测试Sender,以便找到调用这个事件的处理句柄或组件的类型。如,我们将窗口中的编辑框和标签的Click事件的处理句柄都指向窗口的xxx函数(其实你只要先把一个控件的Click事件命名为xxx,并在其中写上共享代码,其它控件的Click事件都指向xxx就行了),本例中的编辑框和标签对Click事件将有不同的反应,代码如下:

    void __fastcall TForm1::xxx(TObject *Sender)

    {

    if(dynamic_cast<TEdit *>(Sender))

    ShowMessage(\”This is a editbox\”);

    if(dynamic_cast<TLabel *>(Sender))

    ShowMessage(\”This is a label\”);

    }

    当然若是多个同类组件,只是想共用一个事件,那要比这简单多了。举个例子,若你的很多编辑框(Edit),你想在输入某一项的时候先把这一项清空,你只要写一个OnEnter事件就可以了:

    void __fastcall TForm1::Edit1Enter(TObject *Sender)

    {

    TEdit *Edittemp=(TEdit*)(Sender);//把不同的编辑框统一起来

    Edittemp->Text=\”\”;

    }

    其它的Edit组件的OnEnter事件都指向Edit1Enter,这样就行了,试一下,是不是鼠标放在编辑框里一点就清空了J其实这里只是把不同的编辑框(Sender清楚是那一个编辑框)统一起来,好用一个共同的事件来处理。你在同一组件共用同一事件时一定要注意这一点。

    2.强制进行类型转换

    将若干继承同一父类的子类强制转换成该父类。如窗口中有一个TEdit类控件和一个TMemo控件,它们实际上都继承于TCustomEdit类,如果你要为二者的某一事件提供同样的处理,可以将二者的事件句柄都指向自定义的函数yyy,我们这里仍然是在OnEnter事件中(当然你完全可以在其它事件中完成):

    void __fastcall TForm1::yyy(TObject *Sender)

    {

    dynamic_cast<TCustomEdit &>(*Sender).Text=\”This is some demo text\”;

    }

    或以下的格式:

    void __fastcall TForm1::yyy(TObject *Sender)

    {

    dynamic_cast<TCustomEdit* >(Sender)->Text=\”This is some demo text\”;

    }

    注意二者的区别,这其实这正是“.”与“->”的不同之处,仔细品味一下,你会清楚的。

    上面的两个程式均是先把TEdit类和TMemo类均强制转换成TCustomEdit类,再对其父类的属性进行赋值。

    使用Sender参数可以通过单一函数段处理多类组件,真正体现了BCB的面向对象的重用性。

    利用C++Builder遍历文件目录

    AnsiString mypath=  “C:\\*.*”;
    TSearchRec  mysr;
    if(FindFirst(mypath,faAnyFile,mysr)==0)
    {
    while(FindNext(mysr)==0)
    {
    if(mysr.Name!=”.”&&mysr.Name!=”..”)
    {
    if(mysr.Attr==faDirectory)
    {

    ListBox1->Items->Add(mysr.Name);
    }

    else
    {
    ListBox2->Items->Add(mysr.Name);
    }

    }

    }
    }

    FindClose(mysr);

    Get HD Serial NO:

    #include <vcl.h>
    #pragma hdrstop

    #include “Unit1.h”

    #include <WinIOCtl.h>
    #include <stdio.h>

    #pragma inline

    //—————————————————————————
    #pragma package(smart_init)
    #pragma resource “*.dfm”
    TForm1 *Form1;

    //—————————————————————————
    // IDE NT/2000/XP specific variables
    #define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
    #define DFP_GET_VERSION         SMART_GET_VERSION
    #define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
    #define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA

    const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // read ATAPI device
    const WORD IDE_ATA_IDENTIFY   = 0xEC;   // read ATA device

    const int MAX_IDE_DRIVES = 4;

    // SCSI specific variable
    const DWORD FILE_DEVICE_SCSI             = 0×0000001B;
    const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0×0501);
    const DWORD IOCTL_SCSI_MINIPORT          = 0×0004D008; // see NTDDSCSI.H for definition
    const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;

    typedef struct _SRB_IO_CONTROL
    {
    ULONG HeaderLength;
    UCHAR Signature[8];
    ULONG Timeout;
    ULONG ControlCode;
    ULONG ReturnCode;
    ULONG Length;
    }SRB_IO_CONTROL, *PSRB_IO_CONTROL;

    // main function of read info
    void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);

    // assist function
    char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
    // NT/2000/XP function
    void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
    bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
    BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
    // Windows 9X  function
    void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
    void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
    BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);

    // SCSI Read  function(for NT/2000/XP)
    String __fastcall ReadIDEDriveAsScsiDriveOnNT();
    //—————————————————————————
    // ReadPhysicalDrive
    void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
    {
    switch(Win32Platform)
    {
    case VER_PLATFORM_WIN32_WINDOWS:
    ReadPhysicalDriveOnW9X(pSerList, pModeList);
    break;
    case VER_PLATFORM_WIN32_NT:
    ReadPhysicalDriveOnNT(pSerList, pModeList);
    break;
    default:
    break;
    }
    }
    //—————————————————————————
    // ConvertToString
    char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
    {
    static char szResBuf[1024];
    int nIndex = 0;
    int nPosition = 0;

    // Each integer has two characters stored in it backwards
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    {
    // Get high BYTE for 1st character
    szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
    nPosition++;

    // Get low BYTE for 2nd character
    szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
    nPosition++;
    }

    // End the string
    szResBuf[nPosition] = ”;

    // Cut off the trailing blanks
    for(nIndex = nPosition – 1; nIndex > 0 && ‘ ‘ == szResBuf[nIndex]; nIndex–)
    szResBuf[nIndex] = ”;

    return szResBuf;
    }
    //—————————————————————————
    // Winndows NT4/2000/XP  Code
    //—————————————————————————
    // ReadPhysicalDriveOnNT
    void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
    {
    //  output parametres
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];

    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    {
    HANDLE hPhysicalDriveIOCTL;
    char szDriveName[32];

    sprintf(szDriveName, “\\\\.\\PhysicalDrive%d”, nDrive);
    hPhysicalDriveIOCTL = CreateFile(szDriveName,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, 0, NULL);

    if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    {
    DWORD dwBytesReturned = 0;
    GETVERSIONOUTPARAMS gvopVersionParams;

    // Get the version, etc of PhysicalDrive IOCTL
    ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));

    if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
    &dwBytesReturned, NULL))
    {
    continue;
    }

    if(gvopVersionParams.bIDEDeviceMap > 0)
    {
    // IDE or ATAPI IDENTIFY cmd
    BYTE btIDCmd = 0;
    SENDCMDINPARAMS InParams;
    // Now, get the ID sector for all IDE devices in the system.
    // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    // otherwise use the IDE_ATA_IDENTIFY command
    //
    btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0×10) ?
    IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
    ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));

    if(DoIdentify(hPhysicalDriveIOCTL,
    &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
    (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
    {
    DWORD dwDiskData[256];
    USHORT *pIDSector; // related structure IDSECTOR,see header files
    char szSerialNumber[21];
    char szModelNumber[41];

    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
    for(int i=0; i < 256; i++)
    dwDiskData[i] = pIDSector[i];
    // get serial number
    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));

    // get model number
    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));

    pSerList->Add(szSerialNumber);
    pModeList->Add(szModelNumber);
    }
    }
    CloseHandle (hPhysicalDriveIOCTL);
    }
    }
    }
    //—————————————————————————
    // DoIdentify
    bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
    PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
    PDWORD pdwBytesReturned)
    {
    // Set up data structures for IDENTIFY command.
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    pSCIP->irDriveRegs.bFeaturesReg = 0;
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    pSCIP->irDriveRegs.bCylLowReg  = 0;
    pSCIP->irDriveRegs.bCylHighReg = 0;

    // Compute the drive number.
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;

    // The command can either be IDE identify or ATAPI identify.
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    pSCIP->bDriveNumber = btDriveNum;
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;

    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
    (LPVOID)pSCIP,
    sizeof(SENDCMDINPARAMS) – 1,
    (LPVOID)pSCOP,
    sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE – 1,
    pdwBytesReturned, NULL);
    }
    //—————————————————————————
    // Windows 95/98/ME code
    //—————————————————————————
    // ReadPhysicalDriveOnW9X
    void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
    {
    WORD wOutData[256];
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);

    for(int nDrive = 0; nDrive < 8; nDrive++)
    {
    WORD dwBaseAddress;
    BYTE btMasterSlave;         // Master Or Slave
    bool bIsIDEExist;
    bool IsDiskExist;

    switch(nDrive / 2)
    {
    case 0: dwBaseAddress = 0×01F0; break;
    case 1: dwBaseAddress = 0×0170; break;
    case 2: dwBaseAddress = 0×01E8; break;
    case 3: dwBaseAddress = 0×0168; break;
    }

    btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);

    // enter to Ring0
    ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
    bIsIDEExist, IsDiskExist, wOutData);
    }

    // start to Read
    for(int nDrive = 0; nDrive < 8; nDrive++)
    {
    WORD dwBaseAddress;
    BYTE btMasterSlave;         // Master Or Slave
    bool bIsIDEExist;
    bool bIsDiskExist;
    switch(nDrive / 2)
    {
    case 0: dwBaseAddress = 0×01F0; break;
    case 1: dwBaseAddress = 0×0170; break;
    case 2: dwBaseAddress = 0×01E8; break;
    case 3: dwBaseAddress = 0×0168; break;
    }

    btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);

    // enter to Ring0
    bIsIDEExist  = false;
    bIsDiskExist = false;
    ZeroMemory(wOutData, sizeof(wOutData));

    ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
    bIsIDEExist, bIsDiskExist, wOutData);

    if(bIsIDEExist && bIsDiskExist)
    {
    DWORD dwDiskData[256];
    char  szSerialNumber[21];
    char  szModelNumber[41];

    for(int k=0; k < 256; k++)
    dwDiskData[k] = wOutData[k];

    // get serial number
    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));

    // get model number
    ZeroMemory(szModelNumber, sizeof(szModelNumber));
    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));

    pSerList->Add(szSerialNumber);
    pModeList->Add(szModelNumber);
    }
    }
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
    }
    //—————————————————————————
    //—————————————————————————
    // ReadPhysicalDriveOnW9X_Ring0()
    //
    // dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
    // btMasterSlave = Master(0xA0) Or Slave(0xB0)
    //—————————————————————————
    void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
    BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
    {
    BYTE  btIDTR1[6];
    DWORD dwOldExceptionHook;
    const int nHookExceptionNo = 5;

    BYTE  btIsIDEExist = 0;
    BYTE  btIsDiskExist = 0;
    WORD  wOutDataBuf[256];

    BYTE  btIsFirst = (BYTE)bIsFirst;

    const BYTE btBit00 = 0×01;
    // const BYTE btBit02 = 0×04;
    const BYTE btBit06 = 0×40;
    const BYTE btBit07 = 0×80;
    // const BYTE btERR  = btBit00;
    const BYTE btBusy = btBit07;
    const BYTE btAtaCmd   = 0xEC;
    const BYTE btAtapiCmd = 0xA1;

    __asm
    {
    JMP EnterRing0

    WaitWhileBusy proc

    MOV  EBX, 100000
    MOV  DX, dwBaseAddress
    ADD  DX, 7

    LoopWhileBusy:

    DEC  EBX
    CMP  EBX, 0
    JZ   Timeout
    in   AL, DX
    TEST AL, btBusy
    JNZ  LoopWhileBusy
    JMP  DriveReady

    Timeout:
    JMP  LeaveRing0
    DriveReady:
    RET
    ENDP   // End of WaitWhileBusy Procedure

    SelectDevice proc

    MOV  DX, dwBaseAddress
    ADD  DX, 6
    MOV  AL, btMasterSlave

    out  DX, AL
    RET

    ENDP  // End of SelectDevice Procedure

    SendCmd proc

    MOV DX, dwBaseAddress
    ADD DX, 7
    MOV AL, BL
    out DX, AL
    RET
    ENDP  // End of SendCmd Procedure

    // Ring0
    Ring0Proc:
    PUSHAD

    MOV DX, dwBaseAddress
    ADD DX, 7
    in  AL,DX

    CMP AL,0xFF
    JZ  LeaveRing0
    CMP AL, 0×7F
    JZ  LeaveRing0

    MOV btIsIDEExist, 1

    CALL WaitWhileBusy
    CALL SelectDevice

    CMP  btIsFirst, 1
    JZ   LeaveRing0

    CALL WaitWhileBusy

    TEST AL, btBit06
    JZ   LeaveRing0

    MOV  btIsDiskExist, 1

    CALL WaitWhileBusy
    CALL SelectDevice
    MOV  BL, btAtaCmd
    CALL SendCmd
    CALL WaitWhileBusy

    MOV  DX, dwBaseAddress
    ADD  DX, 7

    in   AL, DX

    TEST AL, btBit00
    JZ   RetrieveInfo

    CALL WaitWhileBusy
    CALL SelectDevice
    MOV  BL, btAtapiCmd
    CALL SendCmd
    CALL WaitWhileBusy

    MOV  DX, dwBaseAddress
    ADD  DX, 7
    in   AL, DX
    TEST AL, btBit00
    JZ   RetrieveInfo
    JMP  LeaveRing0

    RetrieveInfo:

    LEA  EDI, wOutDataBuf
    MOV  ECX, 256
    MOV  DX, dwBaseAddress
    CLD

    REP  INSW

    LeaveRing0:

    POPAD
    IRETD

    EnterRing0:

    SIDT FWORD PTR btIDTR1
    MOV EAX, DWORD PTR btIDTR1 + 02h
    ADD EAX, nHookExceptionNo * 08h + 04h
    CLI

    MOV ECX, DWORD PTR [EAX]
    MOV CX, WORD PTR [EAX-04h]
    MOV dwOldExceptionHook, ECX

    LEA EBX, Ring0Proc
    MOV WORD PTR [EAX-04h],BX
    SHR EBX, 10h
    MOV WORD PTR[EAX+02h], BX

    INT nHookExceptionNo

    MOV ECX,dwOldExceptionHook
    MOV WORD PTR[EAX-04h], CX
    SHR ECX,10h
    MOV WORD PTR[EAX+02h], CX
    STI
    }
    if(!bIsFirst)
    {
    bIsIDEExist  = (bool)btIsIDEExist;
    bIsDiskExist = (bool)btIsDiskExist;
    CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    }
    }

    //—————————————————————————
    __fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
    {
    }
    //—————————————————————————
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);

    }
    //—————————————————————————

     

    DateUtils时间单元说明

    DateUtils时间单元说明
    CompareDate 函数 *比较两个日期时间值日期部分的大小
    CompareDateTime 函数 *比较两个日期时间值的大小
    CompareTime 函数 *比较两个日期时间值时间部分的大小
    DateOf 函数 *去除日期时间值的时间部分
    DateTimeToJulianDate 函数 *转换日期时间值为儒略日
    DateTimeToModifiedJulianDate 函数 *转换日期时间值为改进的儒略日
    DateTimeToUnix 函数 *转换日期时间值为Unix/Linus日期时间值
    Day of week 常量 *ISO 8601标准中一周各天顺序的 常量
    DayOf 函数 *返回一个日期时间值的天
    DayOfTheMonth 函数 *返回一个日期时间值的天
    DayOfTheWeek 函数 *返回一个日期时间值是那星期的第几天
    DayOfTheYear 函数 *返回一个日期时间值是那年的第多少天
    DaysBetween 函数 *返回两个日期时间值之间相差的整数天数
    DaysInAMonth 函数 *返回指定年、月的天数
    DaysInAYear 函数 *返回指定年的天数
    DaysInMonth 函数 *返回一个日期时间值的那个月的天数
    DaysInYear 函数 *返回一个日期时间值的那一年的天数
    DaySpan 函数 *返回两个日期时间值之间相差的小数天数
    DecodeDateDay 过程 *返回一个日期时间值的年份和是一年的第多少天
    DecodeDateMonthWeek 过程 *返回一个日期时间值的年、月、那个月的第几周、那周的第几天
    DecodeDateTime 过程 *返回一个日期时间值的年、月、日、时、分、秒、毫秒
    DecodeDateWeek 过程 *返回一个日期时间值的年、一年的第多少周、一周的第几天
    DecodeDayOfWeekInMonth 过程 *返回一个日期时间值的年、月、一周的第几天、那个月的第几个星期几
    EncodeDateDay 函数 *返回指定年和一年的第多少天的日期时间值
    EncodeDateMonthWeek 函数 *返回指定年、月、那个月的第几周、那周的第几天的日期时间值
    EncodeDateTime 函数 *返回指定年、月、日、时、分、秒,毫秒返的日期时间值
    EncodeDateWeek 函数 *返回指定年、那年的第多少周、那周的第几天的日期时间值
    EncodeDayOfWeekInMonth 函数 *返回指定年、月、那个月的第几个星期几的日期时间值
    EndOfADay 函数 *返回指定年、那年第多少天的最后一秒的日期时间值
    EndOfAMonth 函数 *返回指定年、月的最后一天最后一秒的日期时间值
    EndOfAWeek 函数 *返回指定年、那年第多少周、那周第几天的最后一秒的日期时间值
    EndOfAYear 函数 *返回指定年的最后一天最后一秒的日期时间值
    EndOfTheDay 函数 *返回指定日期时间值的那一天最后一秒的日期时间值
    EndOfTheMonth 函数 *返回指定日期时间值的那个月的最后一天最后一秒的日期时间值
    EndOfTheWeek 函数 *返回指定日期时间值的那一周的最后一天最后一秒的日期时间值
    EndOfTheYear 函数 *返回指定日期时间值的那一年最后一天最后一秒的日期时间值
    HourOf 函数&nbsp;*返回指定日期时间值的小时部分
    HourOfTheDay 函数&nbsp;*返回指定日期时间值的小时部分.
    HourOfTheMonth 函数&nbsp;*返回从指定日期时间值的那个月的第一天0点到指定日期的小时已经度过的小时数
    HourOfTheWeek 函数&nbsp;*返回从指定日期时间值中那一周第一天0点到指定日期的那个小时 已经度过的小时数
    HourOfTheYear 函数&nbsp;*返回从指定日期时间值中 那一年第一天0点到指定日期的那个小时已经度过的小时数
    HoursBetween 函数&nbsp;*返回两个指定日期时间值之间相差的小时数
    HourSpan 函数&nbsp;*返回两个指定日期时间值之间相差的小时数(包括小数部分)
    IncDay 函数&nbsp;*返回日期时间值向后推移指定天数后的值
    IncHour 函数&nbsp;*返回日期时间值向后推移指定小时数的值
    IncMilliSecond 函数&nbsp;*返回日期时间值向后推移指定毫秒数的值
    IncMinute 函数&nbsp;*返回日期时间值向后推移指定分钟数的值
    IncSecond 函数&nbsp;*返回日期时间值向后推移指定秒数的值
    IncWeek 函数&nbsp;*返回日期时间值向后推移指定星期数的值
    IncYear 函数&nbsp;*返回日期时间值向后推移指定星期数的值
    IsInLeapYear 函数&nbsp;*判断指定的日期时间值的年份是否为闰年
    IsPM 函数&nbsp;*判断指定的日期时间值的时间是否是中午12:0:0之后
    IsSameDay 函数&nbsp;*判断一个日期时间值与标准日期时间值是否是同一天
    IsToday 函数&nbsp;*判断一个日期时间值是否是当天
    IsValidDate 函数&nbsp;*判断指定的年、月、日是否是有效的日期
    IsValidDateDay 函数&nbsp;*判断指定的年、该年的天数是否是该年有效的天数
    IsValidDateMonthWeek 函数&nbsp;*判断指定的年、月、该月的第几周、该周的第几天是否是有效的日期
    IsValidDateTime 函数&nbsp;*判断指定的年、月、日、时、分、秒、毫秒是否是有效的日期时间值
    IsValidDateWeek 函数&nbsp;*判断指定的年、该年的第多少周、该周第几天是否是有效的日期
    IsValidTime 函数&nbsp;*判断指定的时、分、秒、毫秒是否是有效的时间
    JulianDateToDateTime 函数&nbsp;*转换儒略日期为日期时间值
    MilliSecondOf 函数&nbsp;*返回指定日期时间值的毫秒部分
    MilliSecondOfTheDay 函数&nbsp;*返回指定日期时间值的那天0时0分0秒0毫秒开始到其指定时间的毫秒数
    MilliSecondOfTheHour 函数&nbsp;*返回指定日期时间值的那一小时0分0秒0毫秒开始到其指定时间的毫秒数
    MilliSecondOfTheMinute 函数&nbsp;*返回指定日期时间值的那一分钟0秒0毫秒开始到其指定时间的毫秒数
    MilliSecondOfTheMonth 函数&nbsp;*返回指定日期时间值的那个月1日分钟0秒0毫秒开始到其指定时间的毫秒数
    MilliSecondOfTheSecond 函数&nbsp;*返回指定日期时间值的毫秒部分
    MilliSecondOfTheWeek 函数&nbsp;*返回指定日期时间值的那周星期一0时0分0秒0毫秒到其指定时间的毫秒数
    MilliSecondOfTheYear 函数&nbsp;*返回指定日期时间值的那年1月1日0时0分0秒0毫秒到其指定时间的毫秒数
    MilliSecondsBetween 函数&nbsp;*返回两个指定日期时间值之间相差的毫秒数(整数)
    MilliSecondSpan 函数&nbsp;*返回两个指定日期时间值 之间相差的毫秒数(小数)
    MinuteOf 函数&nbsp;*返回指定日期时间值 分钟部分
    MinuteOfTheDay 函数&nbsp;*返回指定日期时间值的那天0时0分开始到其指定时间的分钟数
    MinuteOfTheHour 函数&nbsp;*返回指定日期时间值的分钟部分
    MinuteOfTheMonth 函数&nbsp;*返回指定日期时间值的那个月1日0时0分开始到其指定时间的分钟数
    MinuteOfTheWeek 函数&nbsp;*返回指定日期时间值的那周第1天0时0分开始到其指定时间的分钟数
    MinuteOfTheYear 函数&nbsp;*返回指定日期时间值的那年1月1日0时0分开始到其指定时间的分钟数
    MinutesBetween 函数&nbsp;*返回两个指定日期时间值之间相差的分钟数(整数)
    MinuteSpan 函数&nbsp;*返回两个指定日期时间值之间相差的分钟数(包含小数)
    ModifiedJulianDateToDateTime 函数&nbsp;*转换修正的儒略日为日期时间值
    MonthOf 函数&nbsp;*返回指定日期时间值的月份部分
    MonthOfTheYear 函数&nbsp;*返回指定日期时间值的月份部分
    MonthsBetween 函数&nbsp;*返回两个指定日期时间值之间相差的月份(整数)
    MonthSpan 函数&nbsp;*返回两个指定日期时间值之间相差的月份(包含小数)
    NthDayOfWeek 函数&nbsp;*返回指定日期时间值该月的第几个星期几
    OneHour 常量 *Delphi与时间成反比的常量
    OneMillisecond 常量 *Delphi与时间成反比的常量
    OneMinute 常量 *Delphi与时间成反比的常量
    OneSecond 常量 *Delphi与时间成反比的常量
    RecodeDate 函数&nbsp;*替换指定日期时间值的日期部分
    RecodeDateTime 函数&nbsp;*选择替换指定日期时间值
    RecodeDay 函数&nbsp;*替换指定日期时间值 的日部分
    RecodeHour 函数&nbsp;*替换指定日期时间值 的小时部分
    RecodeMilliSecond 函数&nbsp;*替换指定日期时间值的毫秒部分
    RecodeMinute 函数&nbsp;*替换指定日期时间值的分钟部分
    RecodeMonth 函数&nbsp;*替换指定日期时间值的月份部分
    RecodeSecond 函数&nbsp;*替换指定日期时间值的秒部分
    RecodeTime 函数&nbsp;*替换指定日期时间值的时间部分
    RecodeYear 函数&nbsp;*替换指定日期时间值的年份部分
    SameDate 函数&nbsp;*判断两个日期时间值的年、月、日部分是否相同
    SameDateTime 函数&nbsp;*判断两个日期时间值的年、月、日、时、分、秒、毫秒是否相同
    SameTime 函数&nbsp;*判断两个日期时间值的时、分、秒、毫秒部分是否相同
    SecondOf 函数&nbsp;*返回指定日期时间值的秒部分
    SecondOfTheDay 函数&nbsp;*返回从指定日期时间值那天0时0分0秒到其指定时间的秒数
    SecondOfTheHour 函数&nbsp;*返回从指定日期时间值那小时0分0秒到其指定时间的秒数
    SecondOfTheMinute 函数&nbsp;*返回从指定日期时间值那分钟0秒到其指定时间的秒数
    SecondOfTheMonth 函数&nbsp;*返回从指定日期时间值那个月1日0时0分0秒到其指定时间的秒数
    SecondOfTheWeek 函数&nbsp;*返回从指定日期时间值所在周的星期一0时0分0秒到其指定时间的秒数
    SecondOfTheYear 函数&nbsp;*返回从指定日期时间值那年的1月1日0时0分0秒到其指定时间的秒数
    SecondsBetween 函数&nbsp;*返回两个指定日期时间值之间相差的秒数(整数)
    SecondSpan 函数&nbsp;*返回两个指定日期时间值之间相差的秒数(包含小数)
    StartOfADay 函数&nbsp;*返回指定那天开始(0时0分0秒0毫秒)的日期时间值
    StartOfAMonth 函数&nbsp;*返回指定年、月的第一天开始(0时0分0秒0毫秒)的日期时间值
    StartOfAWeek 函数&nbsp;*返回指定年、第多少周、第几天开始(0时0分0秒0毫秒)的日期时间值
    StartOfAYear 函数&nbsp;*返回指定年开始(1月1日0时0分0秒0毫秒)的日期时间值
    StartOfTheDay 函数&nbsp;*返回指定日期时间值那天开始(0时0分0秒0毫秒)的日期时间值
    StartOfTheMonth 函数&nbsp;*返回指定日期时间值那个月开始(1日0时0分0秒0毫秒)的日期时间值
    StartOfTheWeek 函数&nbsp;*返回指定日期时间值那周开始(第一天0时0分0秒0毫秒)的日期时间值
    StartOfTheYear 函数&nbsp;*返回指定日期时间值那年开始(1月1日0时0分0秒0毫秒)的日期时间值
    TimeOf 函数&nbsp;*返回指定日期时间值的时间部分
    Today 函数&nbsp;*返回当天的日期
    Tomorrow 函数&nbsp;*返回下一天的日期
    TryEncodeDateDay 函数&nbsp;*计算指定年、该年第多少天的日期时间值
    TryEncodeDateMonthWeek 函数&nbsp;*计算指定年、月、该月第几周、该周第几天的日期时间值
    TryEncodeDateTime 函数&nbsp;*转换指定年、月、日、时、分、秒、毫秒为日期时间值
    TryEncodeDateWeek 函数&nbsp;*转换指定年、该第多少周、该周第几天为日期时间值
    TryEncodeDayOfWeekInMonth 函数&nbsp;*转换指定年、月、该月第几个星期几为日期时间值
    TryJulianDateToDateTime 函数&nbsp;*转换指定儒略日为日期时间值
    TryModifiedJulianDateToDateTime 函数&nbsp;*转换指定修正儒略日为日期时间值
    TryRecodeDateTime 函数&nbsp;*选择替换指定日期时间值的某些部分
    UnixToDateTime 函数&nbsp;*转换Unix或Linux日期、时间值为Delphi日期时间值
    WeekOf 函数&nbsp;*返回指定日期时间值是某年的第多少周
    WeekOfTheMonth 函数&nbsp;*返回指定日期时间值是某月的第 几周
    WeekOfTheYear 函数&nbsp;*返回指定日期时间值是某年的第多少周
    WeeksBetween 函数&nbsp;*返回两个指定日期时间值 之间相差多少周(整数)
    WeeksInAYear 函数&nbsp;*返回指定的年有多少周
    WeeksInYear 函数&nbsp;*返回指定日期时间值的那年有多少周
    WeekSpan 函数&nbsp;*返回两个指定日期时间值之间相差多少周(包含小数)
    WithinPastDays 函数&nbsp;*判断两个日期之间相差 是否在指定天数的范围内
    WithinPastHours 函数&nbsp;*判断两个日期 时间值之间相差是否在指定小时的范围内
    WithinPastMilliSeconds 函数&nbsp;*判断两个日期时间值之间相差是否在指定毫秒的范围内
    WithinPastMinutes 函数&nbsp;*判断两个日期时间值之间相差是否在指定分钟的范围内
    WithinPastMonths 函数&nbsp;*判断两个日期时间值之间相差是否在指定月份的范围内
    WithinPastSeconds 函数&nbsp;*判断两个日期时间值之间相差是否在指定秒数的范围内
    WithinPastWeeks 函数&nbsp;*判断两个日期时间值之间相差是否在指定星期数的范围内
    WithinPastYears 函数&nbsp;*判断两个日期时间值之间相差是否在指定年数的范围内
    YearOf 函数&nbsp;*返回指定日期时间值中年份部分
    YearsBetween 函数&nbsp;*返回两个指定日期时间值之间相差的年份数(整数)
    YearSpan 函数&nbsp;*返回两个指定日期时间值之间相差的年份数(包含小数)
    Yesterday 函数 *返回当前日期之前一天(昨天)的日期

    通过 SHGetSpecialFolderLocationSHGetPathFromIDList 函数获取常用路径

    Header File:

    #define   NO_WIN32_LEAN_AND_MEAN

    #include <ShlObj.hpp>

     

    Code:

      LPITEMIDLIST pidl;

      char arr_cDesktopPath[MAX_PATH];

     

     SHGetSpecialFolderLocation(Handle, CSIDL_DESKTOP,&pidl);

     SHGetPathFromIDList(pidl,arr_cDesktopPath);

     

     ShowMessage(arr_cDesktopPath);

     

    Parameters:

    CSIDL_DESKTOP         , { = $0000 }
      CSIDL_INTERNET        , { = $0001 }
      CSIDL_PROGRAMS        , { = $0002 }
      CSIDL_CONTROLS        , { = $0003 }
      CSIDL_PRINTERS        , { = $0004 }
      CSIDL_PERSONAL        , { = $0005 }
      CSIDL_FAVORITES        , { = $0006 }
      CSIDL_STARTUP         , { = $0007 }
      CSIDL_RECENT         , { = $0008 }
      CSIDL_SENDTO         , { = $0009 }
      CSIDL_BITBUCKET        , { = $000a }
      CSIDL_STARTMENU        , { = $000b }
      CSIDL_MYDOCUMENTS       , { = $000c }
      CSIDL_MYMUSIC         , { = $000d }
      CSIDL_MYVIDEO         , { = $000e }
      CSIDL_DESKTOPDIRECTORY    , { = $0010 }
      CSIDL_DRIVES         , { = $0011 }
      CSIDL_NETWORK         , { = $0012 }
      CSIDL_NETHOOD         , { = $0013 }
      CSIDL_FONTS          , { = $0014 }
      CSIDL_TEMPLATES        , { = $0015 }
      CSIDL_COMMON_STARTMENU    , { = $0016 }
      CSIDL_COMMON_PROGRAMS     , { = $0017 }
      CSIDL_COMMON_STARTUP     , { = $0018 }
      CSIDL_COMMON_DESKTOPDIRECTORY , { = $0019 }
      CSIDL_APPDATA         , { = $001a }
      CSIDL_PRINTHOOD        , { = $001b }
      CSIDL_LOCAL_APPDATA      , { = $001c }
      CSIDL_ALTSTARTUP       , { = $001d }
      CSIDL_COMMON_ALTSTARTUP    , { = $001e }
      CSIDL_COMMON_FAVORITES    , { = $001f }
      CSIDL_INTERNET_CACHE     , { = $0020 }
      CSIDL_COOKIES         , { = $0021 }
      CSIDL_HISTORY         , { = $0022 }
      CSIDL_COMMON_APPDATA     , { = $0023 }
      CSIDL_WINDOWS         , { = $0024 }
      CSIDL_SYSTEM         , { = $0025 }
      CSIDL_PROGRAM_FILES      , { = $0026 }
      CSIDL_MYPICTURES       , { = $0027 }
      CSIDL_PROFILE         , { = $0028 }
      CSIDL_SYSTEMX86        , { = $0029 }
      CSIDL_PROGRAM_FILESX86    , { = $002a }
      CSIDL_PROGRAM_FILES_COMMON  , { = $002b }
      CSIDL_PROGRAM_FILES_COMMONX86 , { = $002c }
      CSIDL_COMMON_TEMPLATES    , { = $002d }
      CSIDL_COMMON_DOCUMENTS    , { = $002e }
      CSIDL_COMMON_ADMINTOOLS    , { = $002f }
      CSIDL_ADMINTOOLS       , { = $0030 }
      CSIDL_CONNECTIONS       , { = $0031 }
      CSIDL_COMMON_MUSIC      , { = $0035 }
      CSIDL_COMMON_PICTURES     , { = $0036 }
      CSIDL_COMMON_VIDEO      , { = $0037 }
      CSIDL_RESOURCES        , { = $0038 }
      CSIDL_RESOURCES_LOCALIZED   , { = $0039 }
      CSIDL_COMMON_OEM_LINKS    , { = $003a }
      CSIDL_CDBURN_AREA       , { = $003b }
      CSIDL_COMPUTERSNEARME     , { = $003d }
      CSIDL_PROFILES         { = $003e }