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编写的数据库程序在发布时需要同时发布BDE(Borland Database Engine),但BDE占用空间较大(不同版本大小不一,最新的Delphi5有17M多),远比一般的程序本身要大。但实际上,有些文件用不上的,所以我们可以在发布时用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.CNT:BDE帮助文件,可以不要。
BdeAdmin.exe、BdeAdmin.HLP、BdeAdmin.CNT:BDE管理器及帮助文件,如果不会发生要求软件用户自己配置BDE的情况时,可以不要。
DataBump.EXE、DataBump.HLP、DataBump.CNT:数据库数据转移工具及帮助文件,可以不要。
Localsql.HLP、Localsql.CNT:SQL查询语句帮助文件,可以不要。
Sqllnk32.HLP、Sqllnk32.CNT:SQL连接帮助文件,可以不要。在根据需要选择文件后,还要写注册表文件。可以手工设置,但最好在程序中设置,需要设置的注册表键值有(在调用数据库操作前需要有正确的键值存在,各对应键值在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#(字符串值) 其中#为编号,按顺序为0、1、2、3……如:
HKEY_LOCAL_MACHINE\Software\Borland\BLW32\LOCALE_LIB0=”fareasst.btl” HKEY_LOCAL_MACHINE\Software\Borland \BLW32\LOCALE_LIB1=”usa.btl”
做完这些就足够了,按此办法即可有效减少BDE驱动程序的大小,例如只用TTable控件操作Paradox数据库,则只要Idapi32.dll、Blw32.dll、Idr20009.dll、Fareast.btl、Usa.btl、Idpdx32.dll六个文件即可。这些文件可放在任何一个目录,只要在注册表指明即可。BDE由17.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.dll、Usa.btl、Idapi.cfg、Charset.cvb、Bantam.dll、BLW32.dll、Idapi32.dll、Fareast.btl、Idpdx32.dll、Idr20009.dll、Idsql32.dll(以上文件必须含目录路径);
4.在Dialog Boxes中设置所需安装对话框;
5.在Make Registry Changes中设置Keys项,在HKEY_LOCAL_MACHINE中加入software\borland\blw32和software\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 Installation和Create 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
{
AnsiString AccessDll;
AnsiString S;
TRegistry *Registry = new TRegistry;
try
{
Registry->RootKey = HKEY_LOCAL_MACHINE;
{
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();
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->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->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”,”");
{
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;
}
}
判断windows的Desktop及其它目录 使用API函数SHGetSpecialFolder。shlobj.h里有SHGetSpecialFolder的原型声明。这个函数可以帮我们找到windows的Desktop目录、启动目录、我的文档目录等。 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,然后设定TClientDataset的IndexName就可以了。
ClientDataSet使用心得和技巧
http://blog.sina.com.cn/s/blog_59cb8a930100aw4v.html
影响ClientDataSet处理速度的一个因素
TClientDataSet是Delphi开发数据库时一个非常好的控件。有很强大的功能。
我常常用ClientDataSet做MemoryDataSet来使用。还可以将ClientDataSet的数据保存为XML,这样就可以做简单的本地数据库使用。还有很多功能就不多说了。在使用ClientDataSet的过程中关于怎样提高处理速度这个问题,我就我个人的一点点体会和大家分享一下。
通常情况下我们一般都是用
…ClientDataSet–>DataSource–>DBComponent
这样的结构,处理数据的时候就直接操作ClientDataSet。但是大多DBComponet都会立即响应ClientDataSet的变化。如果你是向ClientDataSet中插入很多数据时候,DBComponent就要响应几次,而且响应过程根据不同的控件,速度,过程数量都不一样。这样就影响了程序的执行效率。所以在对ClientDataSet处理中,我是用ClientDataSet.DisableControls和ClientDataSet.EnableControls方法:打开和关闭DBComponent与ClientDataSet的数据显示关系。
例如:
ClientDataSet..DisableControls;
…
for I := 0 to 10000 do
begin
ClientDataSet.Append;
…
ClientDataSet.Post;
end;
…
ClientDataSet.EnableControls
…
这样做以后你会发现处理速度比以前没有使用方法的时候有成倍的提高。
我所介绍的心得和技巧都是用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;
最老,但是最快的查找方式。
使用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的查找,还需要了解ClientDataSet和Index机制。这里就不详细说明Index机制。一个基本的原则,要有Index,才能查找。
4.Locating 查找数据
2,3两种查找方式都是基于Index的,但是在实际应用中,可能会查找IndexField以外的Field。那我们就可以使用Locate。但是查找速度是没有2,3两种快的。比如:如果你查找一条纪录9000/10000,Locate需要500ms,Scanning需要>2s,FindKey只要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.DisableControls和ClientDataSet.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对象的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;
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 刚可以实现。
upWhereAll 限制最严,但可以最大程度地保证记录的一致性。如果两个用户编辑同一条记录,第一个用户能够更新记录,而第二个用户将会收到“另一个用户已经修改了这条记录”的报错信息。如果希望改进执行这种检查的字段,可以去掉相应的TField.ProviderFlags属性中的pfInWhere项。
系统默认的是upWhereAll,请修改为你认为合适的模式!
在使用 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
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 刚可以实现。
upWhereAll 限制最严,但可以最大程度地保证记录的一致性。如果两个用户编辑同一条记录,第一个用户能够更新记录,而第二个用户将会收到“另一个用户已经修改了这条记录”的报错信息。如果希望改进执行这种检查的字段,可以去掉相应的TField.ProviderFlags属性中的pfInWhere项。
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 }
=============================================================
|
在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参数实现代码重用(修正版) | |
|
利用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 函数 *返回指定日期时间值的小时部分
HourOfTheDay 函数 *返回指定日期时间值的小时部分.
HourOfTheMonth 函数 *返回从指定日期时间值的那个月的第一天0点到指定日期的小时已经度过的小时数
HourOfTheWeek 函数 *返回从指定日期时间值中那一周第一天0点到指定日期的那个小时 已经度过的小时数
HourOfTheYear 函数 *返回从指定日期时间值中 那一年第一天0点到指定日期的那个小时已经度过的小时数
HoursBetween 函数 *返回两个指定日期时间值之间相差的小时数
HourSpan 函数 *返回两个指定日期时间值之间相差的小时数(包括小数部分)
IncDay 函数 *返回日期时间值向后推移指定天数后的值
IncHour 函数 *返回日期时间值向后推移指定小时数的值
IncMilliSecond 函数 *返回日期时间值向后推移指定毫秒数的值
IncMinute 函数 *返回日期时间值向后推移指定分钟数的值
IncSecond 函数 *返回日期时间值向后推移指定秒数的值
IncWeek 函数 *返回日期时间值向后推移指定星期数的值
IncYear 函数 *返回日期时间值向后推移指定星期数的值
IsInLeapYear 函数 *判断指定的日期时间值的年份是否为闰年
IsPM 函数 *判断指定的日期时间值的时间是否是中午12:0:0之后
IsSameDay 函数 *判断一个日期时间值与标准日期时间值是否是同一天
IsToday 函数 *判断一个日期时间值是否是当天
IsValidDate 函数 *判断指定的年、月、日是否是有效的日期
IsValidDateDay 函数 *判断指定的年、该年的天数是否是该年有效的天数
IsValidDateMonthWeek 函数 *判断指定的年、月、该月的第几周、该周的第几天是否是有效的日期
IsValidDateTime 函数 *判断指定的年、月、日、时、分、秒、毫秒是否是有效的日期时间值
IsValidDateWeek 函数 *判断指定的年、该年的第多少周、该周第几天是否是有效的日期
IsValidTime 函数 *判断指定的时、分、秒、毫秒是否是有效的时间
JulianDateToDateTime 函数 *转换儒略日期为日期时间值
MilliSecondOf 函数 *返回指定日期时间值的毫秒部分
MilliSecondOfTheDay 函数 *返回指定日期时间值的那天0时0分0秒0毫秒开始到其指定时间的毫秒数
MilliSecondOfTheHour 函数 *返回指定日期时间值的那一小时0分0秒0毫秒开始到其指定时间的毫秒数
MilliSecondOfTheMinute 函数 *返回指定日期时间值的那一分钟0秒0毫秒开始到其指定时间的毫秒数
MilliSecondOfTheMonth 函数 *返回指定日期时间值的那个月1日分钟0秒0毫秒开始到其指定时间的毫秒数
MilliSecondOfTheSecond 函数 *返回指定日期时间值的毫秒部分
MilliSecondOfTheWeek 函数 *返回指定日期时间值的那周星期一0时0分0秒0毫秒到其指定时间的毫秒数
MilliSecondOfTheYear 函数 *返回指定日期时间值的那年1月1日0时0分0秒0毫秒到其指定时间的毫秒数
MilliSecondsBetween 函数 *返回两个指定日期时间值之间相差的毫秒数(整数)
MilliSecondSpan 函数 *返回两个指定日期时间值 之间相差的毫秒数(小数)
MinuteOf 函数 *返回指定日期时间值 分钟部分
MinuteOfTheDay 函数 *返回指定日期时间值的那天0时0分开始到其指定时间的分钟数
MinuteOfTheHour 函数 *返回指定日期时间值的分钟部分
MinuteOfTheMonth 函数 *返回指定日期时间值的那个月1日0时0分开始到其指定时间的分钟数
MinuteOfTheWeek 函数 *返回指定日期时间值的那周第1天0时0分开始到其指定时间的分钟数
MinuteOfTheYear 函数 *返回指定日期时间值的那年1月1日0时0分开始到其指定时间的分钟数
MinutesBetween 函数 *返回两个指定日期时间值之间相差的分钟数(整数)
MinuteSpan 函数 *返回两个指定日期时间值之间相差的分钟数(包含小数)
ModifiedJulianDateToDateTime 函数 *转换修正的儒略日为日期时间值
MonthOf 函数 *返回指定日期时间值的月份部分
MonthOfTheYear 函数 *返回指定日期时间值的月份部分
MonthsBetween 函数 *返回两个指定日期时间值之间相差的月份(整数)
MonthSpan 函数 *返回两个指定日期时间值之间相差的月份(包含小数)
NthDayOfWeek 函数 *返回指定日期时间值该月的第几个星期几
OneHour 常量 *Delphi与时间成反比的常量
OneMillisecond 常量 *Delphi与时间成反比的常量
OneMinute 常量 *Delphi与时间成反比的常量
OneSecond 常量 *Delphi与时间成反比的常量
RecodeDate 函数 *替换指定日期时间值的日期部分
RecodeDateTime 函数 *选择替换指定日期时间值
RecodeDay 函数 *替换指定日期时间值 的日部分
RecodeHour 函数 *替换指定日期时间值 的小时部分
RecodeMilliSecond 函数 *替换指定日期时间值的毫秒部分
RecodeMinute 函数 *替换指定日期时间值的分钟部分
RecodeMonth 函数 *替换指定日期时间值的月份部分
RecodeSecond 函数 *替换指定日期时间值的秒部分
RecodeTime 函数 *替换指定日期时间值的时间部分
RecodeYear 函数 *替换指定日期时间值的年份部分
SameDate 函数 *判断两个日期时间值的年、月、日部分是否相同
SameDateTime 函数 *判断两个日期时间值的年、月、日、时、分、秒、毫秒是否相同
SameTime 函数 *判断两个日期时间值的时、分、秒、毫秒部分是否相同
SecondOf 函数 *返回指定日期时间值的秒部分
SecondOfTheDay 函数 *返回从指定日期时间值那天0时0分0秒到其指定时间的秒数
SecondOfTheHour 函数 *返回从指定日期时间值那小时0分0秒到其指定时间的秒数
SecondOfTheMinute 函数 *返回从指定日期时间值那分钟0秒到其指定时间的秒数
SecondOfTheMonth 函数 *返回从指定日期时间值那个月1日0时0分0秒到其指定时间的秒数
SecondOfTheWeek 函数 *返回从指定日期时间值所在周的星期一0时0分0秒到其指定时间的秒数
SecondOfTheYear 函数 *返回从指定日期时间值那年的1月1日0时0分0秒到其指定时间的秒数
SecondsBetween 函数 *返回两个指定日期时间值之间相差的秒数(整数)
SecondSpan 函数 *返回两个指定日期时间值之间相差的秒数(包含小数)
StartOfADay 函数 *返回指定那天开始(0时0分0秒0毫秒)的日期时间值
StartOfAMonth 函数 *返回指定年、月的第一天开始(0时0分0秒0毫秒)的日期时间值
StartOfAWeek 函数 *返回指定年、第多少周、第几天开始(0时0分0秒0毫秒)的日期时间值
StartOfAYear 函数 *返回指定年开始(1月1日0时0分0秒0毫秒)的日期时间值
StartOfTheDay 函数 *返回指定日期时间值那天开始(0时0分0秒0毫秒)的日期时间值
StartOfTheMonth 函数 *返回指定日期时间值那个月开始(1日0时0分0秒0毫秒)的日期时间值
StartOfTheWeek 函数 *返回指定日期时间值那周开始(第一天0时0分0秒0毫秒)的日期时间值
StartOfTheYear 函数 *返回指定日期时间值那年开始(1月1日0时0分0秒0毫秒)的日期时间值
TimeOf 函数 *返回指定日期时间值的时间部分
Today 函数 *返回当天的日期
Tomorrow 函数 *返回下一天的日期
TryEncodeDateDay 函数 *计算指定年、该年第多少天的日期时间值
TryEncodeDateMonthWeek 函数 *计算指定年、月、该月第几周、该周第几天的日期时间值
TryEncodeDateTime 函数 *转换指定年、月、日、时、分、秒、毫秒为日期时间值
TryEncodeDateWeek 函数 *转换指定年、该第多少周、该周第几天为日期时间值
TryEncodeDayOfWeekInMonth 函数 *转换指定年、月、该月第几个星期几为日期时间值
TryJulianDateToDateTime 函数 *转换指定儒略日为日期时间值
TryModifiedJulianDateToDateTime 函数 *转换指定修正儒略日为日期时间值
TryRecodeDateTime 函数 *选择替换指定日期时间值的某些部分
UnixToDateTime 函数 *转换Unix或Linux日期、时间值为Delphi日期时间值
WeekOf 函数 *返回指定日期时间值是某年的第多少周
WeekOfTheMonth 函数 *返回指定日期时间值是某月的第 几周
WeekOfTheYear 函数 *返回指定日期时间值是某年的第多少周
WeeksBetween 函数 *返回两个指定日期时间值 之间相差多少周(整数)
WeeksInAYear 函数 *返回指定的年有多少周
WeeksInYear 函数 *返回指定日期时间值的那年有多少周
WeekSpan 函数 *返回两个指定日期时间值之间相差多少周(包含小数)
WithinPastDays 函数 *判断两个日期之间相差 是否在指定天数的范围内
WithinPastHours 函数 *判断两个日期 时间值之间相差是否在指定小时的范围内
WithinPastMilliSeconds 函数 *判断两个日期时间值之间相差是否在指定毫秒的范围内
WithinPastMinutes 函数 *判断两个日期时间值之间相差是否在指定分钟的范围内
WithinPastMonths 函数 *判断两个日期时间值之间相差是否在指定月份的范围内
WithinPastSeconds 函数 *判断两个日期时间值之间相差是否在指定秒数的范围内
WithinPastWeeks 函数 *判断两个日期时间值之间相差是否在指定星期数的范围内
WithinPastYears 函数 *判断两个日期时间值之间相差是否在指定年数的范围内
YearOf 函数 *返回指定日期时间值中年份部分
YearsBetween 函数 *返回两个指定日期时间值之间相差的年份数(整数)
YearSpan 函数 *返回两个指定日期时间值之间相差的年份数(包含小数)
Yesterday 函数 *返回当前日期之前一天(昨天)的日期
通过 SHGetSpecialFolderLocation、SHGetPathFromIDList 函数获取常用路径
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:
|
|