delphi组件] TOpenDialog 用于显示一个“文件选择”对话框
打开对话框组件(TOpenDialog)TOpenDialog组件用于显示一个“文件选择”对话框,俗称打开对话框。它显示时,在一个列表框中显示当前目录下的所有文件名,用户通过鼠标或键盘,指定其中一个文件名,单击“OK”按钮,就完成了选择文件的操作。
1.TOpenDialog组件的典型用法
“打开”对话框是用TOpenDialog组件实现的,TOpenDialog组件是非可视组件。
Filter属性用于设置文件过滤器,让对话框只列出特定类型的文件。在设计时可以单击Filter属性旁的省略号“.”按钮,打开“Filter.Editor”对话框,在“Filter.Name”栏键入关于过滤器的简短说明,在“Filter”栏键入通配符,在设计期,把“打开”对话框组件加到窗体上,看到的是TOpenDialog组件的图标,只有调用对话框的Execute方法,才能在运行期看到真正的对话框。
2.TOpenDialog组件的重要属性
DefaultExt-------------此属性用于指定一个默认的扩展名
FileName---------------此属性用于指定一个文件名
Files------------------通过此属性可以访问多个文件
Filter-----------------此属性用于设置文件过滤器
FilterIndex------------此属性用于指定哪个过滤器是默认过滤器
InitialDir-------------设置此属性可以指定另外一个目录
Options----------------此属性用于设置“打开”对话框的选项
Title------------------此属性用于设置对话框的标题
(1)DefaultExt属性
此属性用于指定一个默认的扩展名。如果用户在对话框中选择的文件没有带扩展名,就用这个属性作为文件的扩展名,如果不需要默认扩展名,应当把这个属性设为空。
(2)FileName属性
FileName属性可以指定一个文件名。在打开对话框时,这个文件名出现在对话框的“文件名”框中。在对话框中,可以指定其他文件名,如果单击“OK”按钮,对话框将关闭,并且FileName属性变成用户新指定的文件名,包括文件的路径和扩展名。FileName属性也可以指定一个不存在的文件名,表示将打开一个新文件。
(3)Files属性
如果Options属性包含ofAllowMultiSelect元素,表示允许一次选择多个文件,这些文件可以通过Files属性访问。Files属性是一个TStrings对象。
(4)Filter属性
此属性用于设置文件过滤器,让对话框只列出特定类型的文件。在设计时,可以单击 Filter属性旁的“...”按钮,打开“Filter Editor”对话框,在“Filter Name”栏键入关于过滤器的简短说明,在“Filter”栏键入通配符,例如通配符“*.txt”表示让对话框只显示扩展名为.txt的文件。当然,用户可以在“打开”对话框的“文件名”框内直接输入一个扩展名不为 .txt文件名的文件。同时,Filter属性可以设置多个过滤器,这些过滤器将显示在“打开”对话框的“文件类型”组合框内。
(5)FilterIndex属性
如果有多个过滤器,这个属性用于指定哪个过滤器是默认过滤器。默认过滤器将显示在“打开”对话框的“文件类型”组合框的编辑框中。注意,过滤器的序号从1开始。
(6)InitialDir属性
此属性用于设置打开对话框第1次打开时的默认打开目录。例如要将打开对话框的默认打开目录设置为C盘根目录,就可以将InitialDir属性设置为“C:\”。
(7)Options属性
此属性用于设置“打开”对话框的选项。它设定了如下16个用户可选值。
. ofAllowMultiSelect:用户可以一次选择多个文件。
. ofCreatePrompt:如果用户输入的文件名是不存在的,当用户单击“OK”按钮时,将显示一个提示框,询问要不要建立这个文件。
. ofExtensionDifferent:如果用户所选文件的扩展名与DefaultExt属性设置的默认扩展名不同,就包含这个元素。
. ofFileMustExist:用户输入的文件名必须是已存在的。
. ofHideReadOnly:对话框中不显示“以只读方式打开”复选框。
. ofNoChangeDir:即使用户在对话框中选择了其他目录,但对程序来说,当前目录总是对话框第一次打开时的目录。
. ofNoDereferenceLinks:如果用户选择的是快捷方式文件(.lnk),FileName属性是快捷方式文件本身,而不是快捷文件指向的文件。
. ofNoLongNames:不允许长文件名。
. ofNoReadOnlyReturn:不允许用户选择只读的文件,否则将显示一个警告框。
. ofNoTestFileCreate:保存文件时不进行写保护、磁盘满、驱动器门打开等检查。
. ofNoValidate:不对文件名中的字符进行合法性检查。
. ofOverwritePrompt:用于“另存为”对话框中,如果用户指定的文件名已存在,将显示一个警告框用来让用户选择是否要覆盖已有的文件。
. ofPathMustExist:用户输入的路径必须是已经存在的,否则将显示警告。
. ofReadOnly:选中“以只读方式打开”复选框。
. ofShareAware:对话框不理会所有的共享错误。
. ofShowHelp:对话框中将显示“帮助”按钮。
(8)Title属性
此属性用于设置对话框显示时的窗口标题。例如大多数据库程序都有还原数据库功能,其打开对话框的标题就可以设置为“打开还原文件”。
3.TOpenDialog组件的重要事件
OnCanClose----------当用户试图关闭对话框时将触发这个事件
OnFolderChange------当用户在对话框中改变、扩展或折叠了一个目录(也叫文件夹),将触发该事件
OnSelectionChange---当用户打开对话框、选择某个目录或文件、选择另一个过滤器、建立一个新的目录时将触
发这个事件
OnShow--------------当对话框调用Execute方法、并且对话框还未显示时触发此事件
OnTypeChange--------当用户在对话框中选择了另一个过滤器时,将发生这个事件
(1)OnCanClose事件
当用户试图关闭对话框时将触发这个事件。这样就有机会对用户输入的文件名进行检查。如果文件名不符合要求,就把CanClose参数设为False,表示不允许关闭对话框。
(2)OnFolderChange事件
当用户在对话框中改变、扩展或折叠了一个目录(文件夹),将触发该事件。在程序中可以利用此事件获取用户浏览过的目录。
(3)OnSelectionChange事件
当用户打开对话框、选择某个目录或文件、选择另一个过滤器或建立一个新的目录时将触发这个事件。
OnSelectionChange事件与OnFolderChange事件相比触发的概率比较高。
(4)OnTypeChange事件
当用户在对话框中选择了另一个过滤器时,将触发这个事件。在此事件中结合FilterIndex属性的使用,可以获取当前对话。
4.TOpenDialog组件的重要方法
TOpenDialog组件最重要的方法就是Execute方法。此方法能够显示对话框,以供用户设置文件路径及文件名。其使用方法如下:
OpenDialog1.Execute;
Delphi中实现让TListView接收文件拖放
在使用Delphi开发应用程序时常常要使用到TListView列表视控件,但是仅仅使用TListView的原有属性、方法和事件是不够的,常常需要在程序开发过程中对列表视的功能进行扩展,
比如对列表视添加任意列组合排序、ListItem拖动、CustomDraw自绘制、加入背景图等功能,由此可见Delphi自带的TListView列表视控件功能有限,并不让人感到满意。为了让列表视具有更多的功能,我们只有求助于第三方控件,或者自己编写代码对TListView进行改造。
最近我在用Delphi开发一个应用软件的过程中,需要实现让TListView列表视可接收资源管理器或文件管理器文件拖放,并将接收到的文件名和路径显示在TListView列表视中的功能,一下子找不到可以实现此功能的第三方控件,于是便摸索着自己写代码实现了该功能。现将该功能的实现方法整理出来,方便大家以后在工作当中需要使用到类似的功能时做为参考。
一、编程思路
Windows应用程序下实现接收文件的方式是这样的:首先应用程序需要使用VOID DragAcceptFiles(HWND hWnd, BOOL fAccept)函数声明该应用程序中的窗口或控件的句柄可以接受资源管理器或文件管理器发送的WM_DROPFILES消息,窗口或控件的句柄由DragAcceptFiles()参数的hWnd指定,并相应的在应用程序中增加对WM_DROPFILES消息进行处理的代码;当应用程序(准确的说是调用DragAcceptFiles()函数时在参数hWnd中指定的句柄所对应的窗口或控件)接收到WM_DROPFILES消息时,应用程序调用DragQueryFile、DragFinish, DragQueryPoint这三个函数对接收到的消息进行处理,关于这几个函数的详细使用方法和说明请参阅Delphi自带win32.hlp或Microsoft Visual Studio开发包中的MSDN。在Delphi中使用TApplication的OnMessage事件来处理WM_DROPFILES消息。
二、实现步骤
启动Delphi,新建一个工程Project1,从Win32控件面板中拖放一个TListView列表视控件到窗口Form1中,将ViewStyle属性设置为vsReport,接着在ListView1中添加两个列,分别为FileName和Path。好了,列表视设置完成,现在开始在Unit1.Pas进行编码(不要忘了加入shellapi单元),具体如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, shellapi,
ComCtrls;
type
TForm1 = class(TForm)
ListView1: TListView;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
//设置需要处理文件WM_DROPFILES拖放消息
DragAcceptFiles(ListView1.Handle, TRUE);
Application.OnMessage := AppMessage;
end;
procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
nFiles, I: Integer;
Filename: string;
ListItem: TListItem;
begin
//
// 注意!所有消息都将通过这里!
// 不要在此过程中编写过多的或者需要长时间操作的代码,否则将影响程序的性能
//
// 判断是否是发送到ListView1的WM_DROPFILES消息
if (Msg.message = WM_DROPFILES) and (msg.hwnd = ListView1.Handle) then
begin
// 取dropped files的数量
nFiles := DragQueryFile (Msg.wParam, $FFFFFFFF, nil, 0);
// 循环取每个拖下文件的全文件名
try
for I := 0 to nFiles - 1 do
begin
// 为文件名分配缓冲 allocate memory
SetLength (Filename, 80);
// 取文件名 read the file name
DragQueryFile (Msg.wParam, I, PChar (Filename), 80);
Filename := PChar (Filename);
file://将全文件名分解程文件名和路径
ListItem := ListView1.Items.Add;
ListItem.Caption := ExtractFileName(FileName);
ListItem.SubItems.Add(ExtractFilePath(FileName));
end;
finally
//结束这次拖放操作
DragFinish (Msg.wParam);
end;
Handled := True;
end;
end;
end.
delphi TListView的使用
ListView1.Items 为标准 Tlistitems类
ListView1.Items
(1)赋值
with ListView1.Items.Add do
begin
Caption:=caption; //添加第一项
SubItems.add(aaaaa); //添加后面数据
SubItems.add(1234);
SubItems.add(1234);
end; //一定要使用WITH结构.
(2)取值
listview1.Items.Item[i].Caption 取得某条数据标题
listview1.Items.Item[i].SubItems.Strings[j] 取得某条数据内容
listview1.Items.Item[i].SubItems.CommaText 一条记录的全部内容,
格式: "标题","内容1","内容2",....
listview1.Items.Item[i].SubItems.Text 一条记录的全部内容,
格式: 标题,内容,内容2....
(3)删除
listview1.Items.Item[i].Delete; 删除一条数据
(4)数据类型(长度)定义
i:=ListView1.Items.Count 数据条数
listview1.Items.Item[i].Selected 该条数据选中否(MultiSelect决定单选复选)
(5)其他
ListView1.Items.Clear; 清除数据
Delphi ListView的用法(常用技巧)
//增加
i := ListView1.Items.Count;
with ListView1 do
begin
ListItem:=Items.Add;
ListItem.Caption:= IntToStr(i);
ListItem.SubItems.Add('第 '+IntToStr(i)+' 行');
ListItem.SubItems.Add('第三列内容');
end;
//按标题删除
for i:=ListView1.Items.Count-1 downto 0 Do
if ListView1.Items[i].Caption = Edit1.Text then
begin
ListView1.Items.Item[i].Delete(); //删除当前选中行
end;
//选中一行
if ListView1.Selected <> nil then
Edit1.Text := ListView1.Selected.Caption;
// listview1.Items[Listview1.Items.Count -1].Selected := True;
// listview1.Items[Listview1.Items.Count -1].MakeVisible(True);
procedure TForm1.Button2Click(Sender: TObject); // 选择第一条
begin
listview1.SetFocus;
listview1.Items[0].Selected := True;
end;
procedure TForm1.Button1Click(Sender: TObject); // 选择最后一条
begin
listview1.SetFocus;
listview1.Items[Listview1.Items.Count -1].Selected := True;
end;
//这是个通用的过程
procedure ListViewItemMoveUpDown(lv : TListView; Item : TListItem; MoveUp, SetFocus : Boolean);
var
DestItem : TListItem;
begin
if (Item = nil) or
((Item.Index - 1 < 0) and MoveUp) or
((Item.Index + 1 >= lv.Items.Count) and (not MoveUp))
then Exit;
lv.Items.BeginUpdate;
try
if MoveUp then
DestItem := lv.Items.Insert(Item.Index - 1)
else
DestItem := lv.Items.Insert(Item.Index + 2);
DestItem.Assign(Item);
lv.Selected := DestItem;
Item.Free;
finally
lv.Items.EndUpdate;
end;
if SetFocus then lv.SetFocus;
DestItem.MakeVisible(False);
end;
//此为调用过程,可以任意指定要移动的Item,下面是当前(Selected)Item
ListViewItemMoveUpDown(ListView1, ListView1.Selected, True, True);//上移
ListViewItemMoveUpDown(ListView1, ListView1.Selected, False, True);//下移
TListView组件使用方法
引用CommCtrl单元
procedure TForm1.Button1Click(Sender: TObject);
begin
ListView_DeleteColumn(MyListView.Handle, i);//i是要删除的列的序号,从0开始
end;
用LISTVIEW显示表中的信息:
procedure viewchange(listv:tlistview;table:tcustomadodataset;var i:integer);
begin
tlistview(listv).Items.BeginUpdate; {listv:listview名}
try
tlistview(listv).Items.Clear;
with table do {table or query名}
begin
active:=true;
first;
while not eof do
begin
listitem:=tlistview(listv).Items.add;
listitem.Caption:=trim(table.fields[i].asstring);
// listitem.ImageIndex:=8;
next;
end;
end;
finally
tlistview(listv).Items.EndUpdate;
end;
end;
ListView使用中的一些要点。以下以一个两列的ListView为例。
→增加一行:
with ListView1 do
begin
ListItem:=Items.Add;
ListItem.Caption:='第一列内容';
ListItem.SubItems.Add('第二列内容');
end;
→清空ListView1:
ListView1.Items.Clear;
→得到当前被选中行的行的行号以及删除当前行:
For i:=0 to ListView1.Items.Count-1 Do
If ListView1.Items[i].Selected then //i=ListView1.Selected.index
begin
ListView1.Items.Delete(i); //删除当前选中行
end;
当然,ListView有OnSelectItem事件,可以判断选择了哪行,用个全局变量把它赋值出来。
→读某行某列的操作:
Edit1.Text := listview1.Items[i].Caption; //读第i行第1列
Edit2.Text := listview1.Items[i].SubItems.strings[0]; //读第i行第2列
Edit3.Text := listview1.Items[i].SubItems.strings[1]; //读第i行第3列
以次类推,可以用循环读出整列。
→将焦点上移一行:
For i:=0 to ListView1.Items.Count-1 Do
If (ListView1.Items[i].Selected) and (i>0) then
begin
ListView1.SetFocus;
ListView1.Items.Item[i-1].Selected := True;
end;
不过在Delphi6中,ListView多了一个ItemIndex属性,所以只要
ListView1.SetFocus;
ListView1.ItemIndex:=3;
就能设定焦点了。
Delphi的listview能实现交替颜色么?
procedure TForm1.ListView1CustomDrawItem(
Sender: TCustomListView; Item: TListItem; State: TCustomDrawState;
var DefaultDraw: Boolean);
var
i: integer;
begin
i:= (Sender as TListView).Items.IndexOf(Item);
if odd(i) then sender.Canvas.Brush.Color:= $02E0F0D7
else sender.Canvas.Brush.Color:= $02F0EED7;
Sender.Canvas.FillRect(Item.DisplayRect(drIcon));
end;
SHFileOperation
- 函数功能描述:文件操作,与 Shell 的动作相同.
- 函数原型:
- #include
- WINSHELLAPI int WINAPI SHFileOperation(LPSHFILEOPSTRUCT lpFileOp);
- 参数:
- typedef struct _SHFILEOPSTRUCT
- {
- HWND hwnd; //父窗口句柄
- UINT wFunc; //要执行的动作
- LPCTSTR pFrom; //源文件路径,可以是多个文件
- LPCTSTR pTo; //目标路径,可以是路径或文件名
- FILEOP_FLAGS fFlags; //标志,附加选项
- BOOL fAnyOperationsAborted; //是否可被中断
- LPVOID hNameMappings; //文件映射名字,可在其它 Shell 函数中使用
- LPCTSTR lpszProgressTitle; // 只在 FOF_SIMPLEPROGRESS 时,指定对话框的标题。
- } SHFILEOPSTRUCT, FAR *LPSHFILEOPSTRUCT;
- ===================
- vb.net
- Public Structure SHFILEOPSTRUCT
- Dim hwnd As IntPtr
- Dim wFunc As Integer
- Dim pFrom As String
- Dim pTo As String
- Dim fFlags As Short
- Dim fAnyOperationsAborted As Integer
- Dim hNameMappings As IntPtr
- Dim lpszProgressTitle As String
- End Structure
- Public Declare Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (ByRef lpFileOp As SHFILEOPSTRUCT) As Integer
- ======================
- vb:
- Type SHFILEOPSTRUCT
- hWnd As Long
- wFunc As Long
- pFrom As String '必须用 pFrom & vbNullChar & vbNullChar
- pTo As String '同pFrom
- fFlags As Integer
- fAnyOperationsAborted As Boolean
- hNameMappings As Long
- lpszProgressTitle As String
- End Type
- Public Declare Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long
- =======================
- wFunc 可以为:
- /FO_MOVE 0x0001 移动文件
- FO_COPY 0x0002 复制文件
- FO_DELETE 0x0003 删除文件,只使用 pFrom
- FO_RENAME 0x0004 文件重命名
- fFlags可以为:
- FOF_MULTIDESTFILES 0x0001 //pTo 指定了多个目标文件,而不是单个目录
- FOF_CONFIRMMOUSE 0x0002
- FOF_SILENT 0x00044 // 不显示一个进度对话框
- FOF_RENAMEONCOLLISION 0x0008 // 碰到有抵触的名字时,自动分配前缀
- FOF_NOCONFIRMATION 0x0010 // 不对用户显示提示
- FOF_WANTMAPPINGHANDLE 0x0020 // 填充 hNameMappings 字段,必须使用 SHFreeNameMappings 释放
- FOF_ALLOWUNDO 0x0040 // 允许撤销
- FOF_FILESONLY 0x0080 // 使用 *.* 时, 只对文件操作
- FOF_SIMPLEPROGRESS 0x0100 // 简单进度条,意味者不显示文件名。
- FOF_NOCONFIRMMKDIR 0x0200 // 建新目录时不需要用户确定
- FOF_NOERRORUI 0x0400 // 不显示出错用户界面
- FOF_NOCOPYSECURITYATTRIBS 0x0800 // 不复制 NT 文件的安全属性
- FOF_NORECURSION 0x1000 // 不递归目录
- 返回值:
- 函数成功返回 0 ,失败返回非 0 。
- 例子:
- 1. 将 C:\Test.txt 拷贝到 D:\
- SHFILEOPSTRUCT lpsh;
- ZeroMemory(&lpsh,sizeof(lpsh));
- lpsh.hwnd= HWND_DESKTOP;
- lpsh.fFlags=FOF_NOCONFIRMATION|FOF_SIMPLEPROGRESS ;
- lpsh.wFunc=FO_COPY; // FO_MOVE 则是移动
- lpsh.pFrom= "C:\Test.txt";
- lpsh.pTo = "D:\"
- if( 0 != SHFileOperation(&lpsh))
- {
- AfxMessageBox("复制文件出错,请检查");
- return ;
- }
- 2. 删除 D:\Test.txt
- SHFILEOPSTRUCT lpsh;
- ZeroMemory(&lpsh,sizeof(lpsh));
- lpsh.hwnd= HWND_DESKTOP;
- lpsh.fFlags=FOF_NOCONFIRMATION|FOF_SIMPLEPROGRESS ;
- lpsh.wFunc=FO_DELETE;
- lpsh.pFrom= "D:\Test.txt";
- if( 0 != SHFileOperation(&lpsh))
- {
- AfxMessageBox("删除文件出错,请检查");
- return ;
- }
- 3.重命名
- SHFILEOPSTRUCT lpsh;
- ZeroMemory(&lpsh,sizeof(lpsh));
- lpsh.hwnd= HWND_DESKTOP;
- lpsh.fFlags=FOF_NOCONFIRMATION|FOF_SIMPLEPROGRESS ;
- lpsh.wFunc=FO_RENAME;
- lpsh.pFrom= "D:\Test.txt";
- lpsh.pTo = "D:\Test2.txt";
- if( 0 != SHFileOperation(&lpsh))
- {
- AfxMessageBox("重命名文件出错!");
- return ;
- }
- 4.VB
- Public Declare Function SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long
- Public Const FO_COPY = &H2
- Public Const FOF_ALLOWUNDO = &H40
- Public Sub ShellCopyFile(Source As String, Dest As String)
- Dim result As Long
- Dim fileop As SHFILEOPSTRUCT
- With fileop
- .hwnd = 0
- .wFunc = FO_COPY
- .pFrom = Source & vbNullChar & vbNullChar
- .pTo = Dest & vbNullChar & vbNullChar
- .fFlags = FOF_ALLOWUNDO
- End With
- result = SHFileOperation(fileop)
- If result <> 0 Then
- 'Msgbox the error that occurred in the API.
- MsgBox Err.LastDllError, vbCritical Or vbOKOnly
- Else
- If fileop.fAnyOperationsAborted <> 0 Then
- MsgBox "Operation Failed", vbCritical Or vbOKOnly
- End If
- End If
- End Sub
- 单开一个内存,清空,把pForm指向这里,把内容拷进去
- SHFILEOPSTRUCT Op;
- ZeroMemory(&Op, sizeof(Op));
- TCHAR ToBuf[MAX_PATH];
- TCHAR FromBuf[MAX_PATH];
- ZeroMemory(ToBuf, sizeof(ToBuf));
- ZeroMemory(FromBuf, sizeof(FromBuf));
- lstrcpy(FromBuf, strDeleteFile);
- Op.hwnd = NULL;
- Op.pFrom = FromBuf;
- Op.pTo = ToBuf;
- Op.fFlags = FOF_NOCONFIRMATION ¦ FOF_NOCONFIRMMKDIR ¦ FOF_NOERRORUI;
- Op.fAnyOperationsAborted = FALSE;
- Op.hNameMappings = NULL;
- Op.lpszProgressTitle = NULL;
- Op.wFunc = FO_DELETE;
- SHFileOperation(&Op);
最新评论