TMediaPlayer.Display 屬性為 TWinControl,播放器利用其 Handle 繪製影片。TWinControl.Handle 唯讀且 GetHandle 為靜態方法,要重導向需兩種方式:修改 VCL 原始碼(不推薦)或繼承並隱藏 GetHandle。採用第二種方式並微調 TMediaPlayer.SetDisplay 以支援新類別。
type
TSurpriseDisplay = class(TWinControl)
protected
function GetHandle: HWND; virtual;
public
property Handle: HWND read GetHandle;
end;
TMediaPlayer = class(Vcl.MPlayer.TMediaPlayer)
protected
procedure SetDisplay(Value: TWinControl); override;
end;
修改後的 SetDisplay:
procedure TMediaPlayer.SetDisplay(Value: TWinControl);
var AWindowParm: TMCI_Anim_Window_Parms; Wnd: HWND;
begin
if (Value <> nil) and MCIOpened and FHasVideo then
begin
FFlags := mci_Wait or mci_Anim_Window_hWnd;
// 關鍵:若為 TSurpriseDisplay 子類則呼叫其虛擬 GetHandle
if Value is TSurpriseDisplay then
Wnd := TSurpriseDisplay(Value).Handle
else
Wnd := Value.Handle;
AWindowParm.Wnd := Longint(Wnd);
// ... 其餘原始邏輯
end;
end;
1. 桌面背景播放:
function TSurpriseDisplay.GetHandle: HWND;
begin
Result := GetDesktopWindow; // 返回桌面視窗控制代碼
end;
MediaPlayer1.Display := TSurpriseDisplay.Create(Self);
2. 記事本視窗播放:
type
TNotepadDisplay = class(TSurpriseDisplay)
private FWnd: HWND;
protected
function GetHandle: HWND; override;
end;
function TNotepadDisplay.GetHandle: HWND;
begin
if FWnd = 0 then
begin
WinExec('notepad.exe', SW_SHOW);
FWnd := FindWindow('Notepad', '無標題 - 記事本'); // 繁體中文視窗標題
end;
Result := FWnd;
end;
MediaPlayer1.Display := TNotepadDisplay.Create(Self);
3. 其他視窗播放: 同理繼承 TSurpriseDisplay,覆寫 GetHandle 返回目標視窗 Handle(如計算機、畫圖、瀏覽器等)。
GetHandle 宣告為 virtual 允許多層繼承覆寫SetDisplay 中的 is 判斷確保相容原有 TWinControl 用法