实例介绍
【实例简介】桌面管理器主窗口单元
功能:提供视频文件管理的主界面,包括文件拖拽、视频预览、搜索、编辑等功能
支持视频格式:mp4, avi, mkv, mov, wmv, flv, webm, mpg, mpeg, m4v, 3gp, ts, m2ts, vob, ogv, divx
主要功能:
- 视频文件扫描和数据库管理
- 视频预览播放(支持静音、循环播放)
- 文件拖拽导入
- 按演员、类型、关键词搜索
- 右键菜单操作(播放、编辑、删除等)
【实例截图】
【核心代码】
unit MainForm;
interface
uses
SysUtils, Messages, ShellAPI, Math, {$I XCGuiStyle.inc}, UI_MainForm, NetworkSpeedMonitor,
MovieManager, Windows, Classes, Wincodec, MovieInfoEditForm, MovieSearch,
MovieImageUtils, MovieInfoUnit, FileHelpers, VideoDurationUnit, ConfigUnit;
function LoadMainForm: Integer;
function OnVideoSearchComplete(Data: Integer): Integer; stdcall;
type
TMainForm = class(TMainFormUI)
private
FMenuUI: TPopupMenuUI;
FCurrentVideoFile: TVideoFile;
// FVideoDecodeTypeShown: Boolean; // 删除解码类型提示相关
procedure ClearMoviePanelIfListEmpty;
protected
procedure OnDroppedFiles(const FilePaths: TArray<string>); override;
procedure OnVideoFrameDecoded(const AFrameData: Pointer; AWidth, AHeight: Integer; APtsSec: Double; AUserData: Pointer);
procedure OnVideoDecodeComplete(AUserData: Pointer);
procedure OnVideoDecodeError(const AErrorMessage: string; AUserData: Pointer);
// 重写UI单元的事件处理方法
procedure MovieListViewEvents(const ListView: TMovieListViewUI; EventType: UINT; ItemIndex: wParam; UserData: lParam); override;
procedure ActorsListViewEvents(const ListView: TActorsListViewUI; EventType: UINT; ActorName: wParam; UserData: lParam); override;
procedure SearchEditEvents(const SearchEdit: TSearchEditUI; EventType: UINT; SearchText: PWideChar; UserData: lParam); override;
procedure MenuEvents(EventType: UINT; MenuID: wParam; UserData: lParam); override;
procedure ButtonClick(const Button: TSvgBtnUI); override;
procedure ButtonCheck(const Button: TSvgBtnUI); override;
public
destructor Destroy; override;
procedure UpdateMovieListView(const FilePath: string; const MovieTitle: string; Status: TMovieOperationStatus; IsComplete: Boolean);
procedure SetConfig;
procedure LoadConfig;
end;
implementation
var
Form: TMainForm;
SpeedManager: TNetworkSpeedMonitor;
MovieSQLManager: TMovieSQLManager;
SearchThread: TVideoSearchThread;
Config: TConfig;
function LoadMainForm;
var
ConfigFile: string;
begin
InitializeDirectories;
// 创建配置对象
Config := TConfig.Create;
ConfigFile := IncludeTrailingPathDelimiter(GetCurrentDir) 'config.json';
Config.LoadFromFile(ConfigFile);
Form := TMainForm.FromXml('main.xml') as TMainForm;
Form.SetMinimumSize(1190, 825);
Form.LoadConfig;
Form.Show;
Result := Form.Handle;
SpeedManager := TNetworkSpeedMonitor.Create(nil);
SpeedManager.OnSpeedUpdated := Form.UpdateNetworkSpeeds;
SpeedManager.Active := True;
MovieSQLManager := TMovieSQLManager.Create(IncludeTrailingPathDelimiter(GetCurrentDir) 'Data\Movie.DB');
MovieSQLManager.SetOperationCallback(Form.UpdateMovieListView);
MovieSQLManager.GetAllMovies;
SearchThread := TVideoSearchThread.Create;
SearchThread.OnComplete := Integer(@OnVideoSearchComplete);
end;
{ TMainForm }
destructor TMainForm.Destroy;
begin
// 保存配置(只更新数据,不保存文件)
SetConfig;
if Assigned(FCurrentVideoFile) then
FCurrentVideoFile.Free;
if Assigned(SearchThread) then
SearchThread.Free;
if Assigned(SpeedManager) then
SpeedManager.Free;
if Assigned(MovieSQLManager) then
MovieSQLManager.Free;
if Assigned(Config) then
Config.Free;
inherited;
end;
function OnVideoSearchComplete(Data: Integer): Integer; stdcall;
var
SearchData: PSearchResultsData;
begin
SearchData := PSearchResultsData(Data);
Form.SetLoadingText(Format('已扫描%d个文件' #13#10 '其中视频文件%d个', [SearchData.ScannedCount, SearchData.MatchedCount]));
if SearchData.IsComplete then
begin
Form.SetLoadingText(Format('已扫描%d个文件' #13#10 '其中视频文件%d个' #13#10 '数据核对请稍等...', [SearchData.ScannedCount, SearchData.MatchedCount]));
// 新增:扫描完成后,状态栏提示
Form.StatusBarText := Format('扫描完成:共扫描%d个文件,视频文件%d个', [SearchData.ScannedCount, SearchData.MatchedCount]);
MovieSQLManager.AddMovies(SearchData.Results);
Form.HideLoading;
end;
Dispose(SearchData);
Result := 0;
end;
procedure TMainForm.OnDroppedFiles(const FilePaths: TArray<string>);
begin
if SearchThread.StartSearch(FilePaths, '*.mp4;*.avi;*.mkv;*.mov;*.wmv;*.flv;*.webm;*.mpg;*.mpeg;*.m4v;*.3gp;*.ts;*.m2ts;*.vob;*.ogv;*.divx') then
begin
ShowLoading('正在加载...');
end
else
MessageBox(Handle, '正忙', '提示', MB_OK);
end;
procedure TMainForm.UpdateMovieListView(const FilePath: string; const MovieTitle: string; Status: TMovieOperationStatus; IsComplete: Boolean);
begin
if FilePath <> '' then
begin
case Status of
/// mosInsertFailed: {插入视频到SQL失败}
// OutputDebugString(PChar(Format('插入影片[%s]失败', [FilePath])));
// mosInsertDuplicate: {插入视频到SQL 已存在}
// OutputDebugString(PChar(Format('影片[%s]已存在,跳过', [FilePath])));
mosQuerySuccess, mosInsertSuccess: {插入视频到SQL 成功}
MovieListViewUI.AddItem(XImage_LoadFile(PChar(GetMovieImagePath(FilePath))), MovieTitle, FilePath);
mosDeleteSuccess:
功能:提供视频文件管理的主界面,包括文件拖拽、视频预览、搜索、编辑等功能
支持视频格式:mp4, avi, mkv, mov, wmv, flv, webm, mpg, mpeg, m4v, 3gp, ts, m2ts, vob, ogv, divx
主要功能:

- 视频文件扫描和数据库管理
- 视频预览播放(支持静音、循环播放)
- 文件拖拽导入
- 按演员、类型、关键词搜索
- 右键菜单操作(播放、编辑、删除等)
【实例截图】
【核心代码】
unit MainForm;
interface
uses
SysUtils, Messages, ShellAPI, Math, {$I XCGuiStyle.inc}, UI_MainForm, NetworkSpeedMonitor,
MovieManager, Windows, Classes, Wincodec, MovieInfoEditForm, MovieSearch,
MovieImageUtils, MovieInfoUnit, FileHelpers, VideoDurationUnit, ConfigUnit;
function LoadMainForm: Integer;
function OnVideoSearchComplete(Data: Integer): Integer; stdcall;
type
TMainForm = class(TMainFormUI)
private
FMenuUI: TPopupMenuUI;
FCurrentVideoFile: TVideoFile;
// FVideoDecodeTypeShown: Boolean; // 删除解码类型提示相关
procedure ClearMoviePanelIfListEmpty;
protected
procedure OnDroppedFiles(const FilePaths: TArray<string>); override;
procedure OnVideoFrameDecoded(const AFrameData: Pointer; AWidth, AHeight: Integer; APtsSec: Double; AUserData: Pointer);
procedure OnVideoDecodeComplete(AUserData: Pointer);
procedure OnVideoDecodeError(const AErrorMessage: string; AUserData: Pointer);
// 重写UI单元的事件处理方法
procedure MovieListViewEvents(const ListView: TMovieListViewUI; EventType: UINT; ItemIndex: wParam; UserData: lParam); override;
procedure ActorsListViewEvents(const ListView: TActorsListViewUI; EventType: UINT; ActorName: wParam; UserData: lParam); override;
procedure SearchEditEvents(const SearchEdit: TSearchEditUI; EventType: UINT; SearchText: PWideChar; UserData: lParam); override;
procedure MenuEvents(EventType: UINT; MenuID: wParam; UserData: lParam); override;
procedure ButtonClick(const Button: TSvgBtnUI); override;
procedure ButtonCheck(const Button: TSvgBtnUI); override;
public
destructor Destroy; override;
procedure UpdateMovieListView(const FilePath: string; const MovieTitle: string; Status: TMovieOperationStatus; IsComplete: Boolean);
procedure SetConfig;
procedure LoadConfig;
end;
implementation
var
Form: TMainForm;
SpeedManager: TNetworkSpeedMonitor;
MovieSQLManager: TMovieSQLManager;
SearchThread: TVideoSearchThread;
Config: TConfig;
function LoadMainForm;
var
ConfigFile: string;
begin
InitializeDirectories;
// 创建配置对象
Config := TConfig.Create;
ConfigFile := IncludeTrailingPathDelimiter(GetCurrentDir) 'config.json';
Config.LoadFromFile(ConfigFile);
Form := TMainForm.FromXml('main.xml') as TMainForm;
Form.SetMinimumSize(1190, 825);
Form.LoadConfig;
Form.Show;
Result := Form.Handle;
SpeedManager := TNetworkSpeedMonitor.Create(nil);
SpeedManager.OnSpeedUpdated := Form.UpdateNetworkSpeeds;
SpeedManager.Active := True;
MovieSQLManager := TMovieSQLManager.Create(IncludeTrailingPathDelimiter(GetCurrentDir) 'Data\Movie.DB');
MovieSQLManager.SetOperationCallback(Form.UpdateMovieListView);
MovieSQLManager.GetAllMovies;
SearchThread := TVideoSearchThread.Create;
SearchThread.OnComplete := Integer(@OnVideoSearchComplete);
end;
{ TMainForm }
destructor TMainForm.Destroy;
begin
// 保存配置(只更新数据,不保存文件)
SetConfig;
if Assigned(FCurrentVideoFile) then
FCurrentVideoFile.Free;
if Assigned(SearchThread) then
SearchThread.Free;
if Assigned(SpeedManager) then
SpeedManager.Free;
if Assigned(MovieSQLManager) then
MovieSQLManager.Free;
if Assigned(Config) then
Config.Free;
inherited;
end;
function OnVideoSearchComplete(Data: Integer): Integer; stdcall;
var
SearchData: PSearchResultsData;
begin
SearchData := PSearchResultsData(Data);
Form.SetLoadingText(Format('已扫描%d个文件' #13#10 '其中视频文件%d个', [SearchData.ScannedCount, SearchData.MatchedCount]));
if SearchData.IsComplete then
begin
Form.SetLoadingText(Format('已扫描%d个文件' #13#10 '其中视频文件%d个' #13#10 '数据核对请稍等...', [SearchData.ScannedCount, SearchData.MatchedCount]));
// 新增:扫描完成后,状态栏提示
Form.StatusBarText := Format('扫描完成:共扫描%d个文件,视频文件%d个', [SearchData.ScannedCount, SearchData.MatchedCount]);
MovieSQLManager.AddMovies(SearchData.Results);
Form.HideLoading;
end;
Dispose(SearchData);
Result := 0;
end;
procedure TMainForm.OnDroppedFiles(const FilePaths: TArray<string>);
begin
if SearchThread.StartSearch(FilePaths, '*.mp4;*.avi;*.mkv;*.mov;*.wmv;*.flv;*.webm;*.mpg;*.mpeg;*.m4v;*.3gp;*.ts;*.m2ts;*.vob;*.ogv;*.divx') then
begin
ShowLoading('正在加载...');
end
else
MessageBox(Handle, '正忙', '提示', MB_OK);
end;
procedure TMainForm.UpdateMovieListView(const FilePath: string; const MovieTitle: string; Status: TMovieOperationStatus; IsComplete: Boolean);
begin
if FilePath <> '' then
begin
case Status of
/// mosInsertFailed: {插入视频到SQL失败}
// OutputDebugString(PChar(Format('插入影片[%s]失败', [FilePath])));
// mosInsertDuplicate: {插入视频到SQL 已存在}
// OutputDebugString(PChar(Format('影片[%s]已存在,跳过', [FilePath])));
mosQuerySuccess, mosInsertSuccess: {插入视频到SQL 成功}
MovieListViewUI.AddItem(XImage_LoadFile(PChar(GetMovieImagePath(FilePath))), MovieTitle, FilePath);
mosDeleteSuccess:
好例子网口号:伸出你的我的手 — 分享!
相关软件
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论