基本信息
源码名称:桌面管理器
源码大小:52.50M
文件格式:.zip
开发语言:Pascal
更新时间:2025-08-05
   友情提示:(无需注册或充值,赞助后即可获取资源下载链接)

     嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300

本次赞助数额为: 2 元 
   源码介绍
桌面管理器主窗口单元
  功能:提供视频文件管理的主界面,包括文件拖拽、视频预览、搜索、编辑等功能
  支持视频格式: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: