急寻wr960204(王锐),关于delphi下directx的使用,双显卡输出问题。欢迎大家讨论(100分)

  • 主题发起人 主题发起人 xiaohedou
  • 开始时间 开始时间
X

xiaohedou

Unregistered / Unconfirmed
GUEST, unregistred user!
我的程序在delphi7下用DelphiX制作,向一个(TDDraw1)surface输出文本图像。目前已经在用了,但缺点是只支持单一显卡。现在需要变为可以同时向两个(或更多)TDDraw输出文字、图像信息。看了你上次给我的代码,对TDDrawPanel和TDDrawItem用法还是没搞通;另外还有TDDrawPanel如何与TDDraw联系。希望再次指教。

也欢迎大家来讨论,分数可以再加。
原帖:http://www.delphibbs.com/delphibbs/dispq.asp?lid=3920065

QQ:929638615 伐木工人
 
就是如何用monitor的GUID动态创建一个TDXDraw,并关联一个TDirectDraw对象
 
TDDrawPanel是我自己写的类。每个显示器上都有一个这样的东西。
多显示器是由多个TDDrawPanel拼接起来的
 
多显示器是由多个TDDrawPanel拼接起来,这个意思我明白。自己创建时没有显示出来。
 
在窗口的WM_Move和WM_Size消息中还要重新计算TDDrawPanel在屏幕上对应的大小。
创建DirectDraw接口实例的时候要指定监视器的GUID。
监视器的GUID要用DirectX提供的枚举监视器的函数获取。
 
1、监视器的GUID要用DirectX提供的枚举监视器的函数获取:这步已经完成;
function DDEnumCallbackEx(lpGUID: PGUID;
lpDriverDescription: PAnsiChar;
lpDriverName: PAnsiChar;
lpContext: Pointer;
Monitor: HMonitor): BOOL;
stdcall;
var guidNull: TGUID;
lpEnumInfo: PEnumInfo;
begin

lpEnumInfo := @lpContext;

ZeroMemory(@guidNull, sizeof(guidNull));

if ((lpGUID <> nil) and (g_Guid.D1 <> guidNull.D1)) then

g_Mulguid := lpGUID^;

if ((lpGUID <> nil) and (g_Guid.D1 = guidNull.D1)) then

begin

g_Guid := lpGUID^;
Inc(MonitorCount);
end;

Result := TRUE;
// Keep enumerating
end;


{$MESSAGE Hint '枚举显示器'}

function EnumerateScreens: HRESULT;
stdcall;
var
hr: HRESULT;
enumInfo: TEnumInfo;
begin

ZeroMemory(@g_Guid, sizeof(TGUID));
ZeroMemory(@g_Mulguid, sizeof(TGUID));
ZeroMemory(@enumInfo, sizeof(TEnumInfo));
enumInfo.bMultimonSupported := TRUE;
hr := DirectDrawEnumerateEx(DDEnumCallbackEx,
@enumInfo, DDENUM_ATTACHEDSECONDARYDEVICES);
if (FAILED(hr)) then
begin

Result := hr;
exit
end;


// If something failed inside the enumeration, be sure to return that HRESULT
if (FAILED(enumInfo.hr)) then

Result := enumInfo.hr;
Result := DD_OK;
end;


2、创建DirectDraw接口实例的时候要指定监视器的GUID:
//主显示器表面设置
hr := DirectDrawCreateEx(@g_Guid, g_pDD, IID_IDirectDraw7, nil);
if (FAILED(hr)) then
begin

Result := E_FAIL;
exit
end;

hr := g_pDD.SetCooperativeLevel(Application.Handle, DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN);
// Set the display mode
hr := g_pDD.SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0, 0);
。。。
hr := g_pDD.CreateSurface(ddsd, g_pFrontSur, nil);
。。。
hr := g_pFrontSur.GetAttachedSurface(ddsCaps, g_pFrontBackSur);

问题:DelphiX的TDXDraw控件和g_pDD(一个ID_IDirectDraw7接口)的关系没搞清,请帮忙解释一下。
原由:以前是用DelphiX的TDXDraw(VCL)放在form上,比如叫dxdraw1;然后
FddSurface := TDirectDrawSurface(dxdraw1);下面对FddSurface做工作就行了;
 
我自己没能:做个用显示器GUID动态创建TDXDraw对象的例子,帮忙给个例子
 
我不会用DelphiX只会直接用DirectX
 
虽然这样,也感谢wr960204。如何创建TDDrawPanel能给个例子吗?

(只因源程序是DelphiX的现在改来不及了。)
 
代码给你贴在下面了.
unit UnitDDrawPanel;

interface
uses
Windows, Classes, SysUtils, Forms, Messages, MultiMon, DirectDraw,
Controls, Graphics, Dialogs;

type
TMMonitor = class(TComponent)
private
FIsDefault: Boolean;
FGUID: TGUID;
FRect: TRect;
FDriverDescription: string;
FDriverName: string;
public
property Rect: TRect read FRect;
end;


TDDrawPanel = class;

TDDrawItem = class(TCustomControl)
private
FMonitor: TMMonitor;
FId: Integer;
FPanleOnwer: TDDrawPanel;
FFormatWidth: Integer;
FFormatHeight: Integer;

FYUVLeft: Integer;
FYUVTop: Integer;
FYUVWidth: Integer;
FYUVHeight: Integer;
private
FFormatSize: Integer;
FFormatUOffset: Integer;
FFormatVOffset: Integer;
//-----------------------
m_lpDD: IDirectDraw7;
m_lpDDSPrimary: IDirectDrawSurface7;
m_lpDDSOffScr: IDirectDrawSurface7;
m_ddsd: TDDSurfaceDesc2;
protected


public
constructor Create(AOwner: TDDrawPanel;
AMonitor: TMMonitor);
destructor Destroy;
override;

procedure Init();
procedure FillYUV(lpYUV: PChar);
function BackSurface(): HRESULT;
procedure SetBounds(ALeft: Integer;
ATop: Integer;
AWidth: Integer;
AHeight: Integer);
override;
end;


TItems = array of TDDrawItem;

TDDrawPanel = class(TForm)
private
FItems: TItems;
FFormatWidth: Integer;
FFormatHeight: Integer;
protected
procedure CreateParams(var Params: TCreateParams);
override;
procedure Clear();
procedure WMActivate(var Message: TWMActivate);
message WM_ACTIVATE;

public
constructor Create(AOwner: TComponent;
AFormatWidth, AFormatHeight: Integer);
destructor Destroy;
override;

public
property Items: TItems read FItems write FItems;
end;


var
MonitorCount : Integer;
Monitors : array of TMMonitor;

//初始化屏幕
procedure InitScreen();
stdcall;

implementation

function DDEnumCallbackEx(lpGUID: PGUID;
lpDriverDescription: PAnsiChar;
lpDriverName: PAnsiChar;
lpContext: Pointer;
Monitor: HMonitor): BOOL;
stdcall;
var
MM : TMMonitor;
mi : TMonitorInfoEx;
begin

MM := TMMonitor.Create(Application);
MM.FIsDefault := lpGUID = nil;
if MM.FIsDefault then

begin

MM.FRect := Rect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
MM.FDriverDescription := lpDriverDescription;
MM.FDriverName := lpDriverName;
end
else

begin

mi.cbSize := SizeOf(TMonitorInfoEx);
GetMonitorInfo(Monitor, @mi);
MM.FGUID := lpGUID^;
MM.FRect := mi.rcMonitor;
MM.FDriverDescription := lpDriverDescription;
MM.FDriverName := lpDriverName;
end;

Inc(MonitorCount);
Result := TRUE;
end;


procedure InitScreen();
procedure Clear();
var
I : Integer;
begin

Monitors := nil;
for I := Application.ComponentCount - 1do
wnto 0do

if Application.Components is TMMonitor then

Application.Components.Free;
end;

var
I, J : Integer;
begin

Clear();
MonitorCount := 0;
DirectDrawEnumerateEx(@DDEnumCallbackEx,
nil,
DDENUM_ATTACHEDSECONDARYDEVICES or DDENUM_NONDISPLAYDEVICES
);
if MonitorCount = 1 then

begin

SetLength(Monitors, MonitorCount);
for I := Application.ComponentCount - 1do
wnto 0do

if (Application.Components is TMMonitor) and
TMMonitor(Application.Components).FIsDefault then

begin

Monitors[0] := TMMonitor(Application.Components);
Break;
end;

end
else

begin

SetLength(Monitors, MonitorCount - 1);
J := 0;
for I := Application.ComponentCount - 1do
wnto 0do

if (Application.Components is TMMonitor) and
(not TMMonitor(Application.Components).FIsDefault) then

begin

Monitors[J] := TMMonitor(Application.Components);
Inc(J);
end;

end;

end;



{ TDDrawPanel }

procedure TDDrawPanel.Clear;
var
I : Integer;
begin

if Length(FItems) = 0 then

Exit;

for I := High(FItems) to Low(FItems)do

begin

FItems.Free;
FItems := nil;
end;

end;



constructor TDDrawPanel.Create(AOwner: TComponent;
AFormatWidth, AFormatHeight: Integer);
var
SCount : Integer;
begin

inherited CreateNew(AOwner);
FFormatWidth := AFormatWidth;
FFormatHeight := AFormatHeight;

SCount := Length(Monitors);
if SCount > 0 then

begin

SetLength(FItems, SCount);
ZeroMemory(@FItems[0], Length(FItems));
end;


end;


procedure TDDrawPanel.CreateParams(var Params: TCreateParams);
begin

inherited CreateParams(Params);
Params.Style := Params.Style and (not WS_CHILD);
end;


destructor TDDrawPanel.Destroy;
begin

Clear();
inherited Destroy;
end;


procedure TDDrawPanel.WMActivate(var Message: TWMActivate);
var
PH : HWND;
begin

if Self.HandleAllocated() and Visible then

SetActiveWindow(GetParent(Self.Handle));
end;





{ TDDrawItem }

function TDDrawItem.BackSurface: HRESULT;
var
Ret : HRESULT;
begin

ZeroMemory(@m_ddsd, sizeof(DDSURFACEDESC2));
m_ddsd.dwSize := sizeof(DDSURFACEDESC2);

m_ddsd.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN or DDSCAPS_VIDEOMEMORY;
//DDSCAPS_OVERLAY DDSCAPS_OFFSCREENPLAIN;
m_ddsd.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH or DDSD_PIXELFORMAT;
m_ddsd.dwWidth := FFormatWidth;
m_ddsd.dwHeight := FFormatHeight;
m_ddsd.ddpfPixelFormat.dwSize := sizeof(DDPIXELFORMAT);
m_ddsd.ddpfPixelFormat.dwFlags := DDPF_FOURCC or DDPF_YUV;
m_ddsd.ddpfPixelFormat.dwFourCC := MAKEFOURCC('Y', 'V', '1', '2');
m_ddsd.ddpfPixelFormat.dwYUVBitCount := 8;

m_lpDDSOffScr := nil;
Ret := m_lpDD.CreateSurface(m_ddsd, m_lpDDSOffScr, nil);
if Ret <> DD_OK then

begin

ShowMessage(DDErrorString(Ret));
Exit;
end;

result := DD_OK;
end;


constructor TDDrawItem.Create(AOwner: TDDrawPanel;
AMonitor: TMMonitor);
var
I : Integer;
begin

inherited Create(AOwner);
FPanleOnwer := AOwner;
FMonitor := AMonitor;
FFormatWidth := FPanleOnwer.FFormatWidth;
FFormatHeight := FPanleOnwer.FFormatHeight;

FFormatSize := FFormatWidth * FFormatHeight;
FFormatUOffset := FFormatSize;
FFormatVOffset := FFormatSize + (FFormatSize shr 2);

FId := -1;
for I := Low(Monitors) to High(Monitors)do

if Monitors = AMonitor then

begin

FId := I;
Break;
end;

{
case FId of
0:
Color := clYellow;
1:
Color := clRed;
2:
Color := clBlack;
3:
Color := clWhite;
end;

}
Color := clBlack;
end;


destructor TDDrawItem.Destroy;
begin


inherited Destroy;
end;



procedure TDDrawItem.FillYUV(lpYUV: PChar);
var
Rect, RectBack : TRect;
lpY, lpU, lpV, lpSurf: PChar;
I : integer;

value1, value2, value3, value4: Integer;
begin


if (not Self.HandleAllocated) or (m_lpDDSOffScr = nil) then

Exit;

GetWindowRect(Handle, Rect);

m_lpDDSOffScr.Lock(nil, m_ddsd, DDLOCK_WAIT or DDLOCK_WRITEONLY, 0);
//------------------------------
lpY := lpYUV;
lpU := lpYUV + FFormatUOffset;
lpV := lpYUV + FFormatVOffset;
lpSurf := m_ddsd.lpSurface;
ZeroMemory(lpSurf, (FFormatWidth * FFormatHeight) * 3 div 2);
//-------------------填充YUV-----------------------------
{
Inc(lpSurf, FFormatWidth * Self.FYUVTop + FYUVLeft);
Inc(lpY, FFormatWidth * Self.FYUVTop);
for I := Self.FYUVTop to Self.FYUVHeight - 1do

begin

Inc(lpY, FYUVLeft);
CopyMemory(lpSurf, lpY, FYUVWidth);
Inc(lpY, FFormatWidth);
Inc(lpSurf, m_ddsd.lPitch);
end;


value1 := m_ddsd.dwHeight div 2;
value2 := m_ddsd.dwWidth div 2;
value3 := FFormatWidth div 2;
value4 := m_ddsd.lPitch div 2;

for i := 0 to value1 - 1do

begin

CopyMemory(lpSurf, lpU, value2);
Inc(lpU, value3);
Inc(lpSurf, value4);
end;


for i := 0 to value1 - 1do

begin

CopyMemory(lpSurf, lpV, value2);
Inc(lpV, value3);
Inc(lpSurf, value4);
end;

}

for I := 0 to FFormatHeight - 1do

begin

CopyMemory(lpSurf, lpY, FFormatWidth);
Inc(lpY, FFormatWidth);
Inc(lpSurf, m_ddsd.lPitch);
end;



value1 := m_ddsd.dwHeight div 2;
value2 := m_ddsd.dwWidth div 2;
value3 := FFormatWidth div 2;
value4 := m_ddsd.lPitch div 2;

for i := 0 to value1 - 1do

begin

CopyMemory(lpSurf, lpU, value2);
Inc(lpU, value3);
Inc(lpSurf, value4);
end;


for i := 0 to value1 - 1do

begin

CopyMemory(lpSurf, lpV, value2);
Inc(lpV, value3);
Inc(lpSurf, value4);
end;


//RectBack := Classes.Rect(0, 0, m_ddsd.dwWidth, m_ddsd.dwHeight);
RectBack := Classes.Rect(FYUVLeft, FYUVTop, FYUVWidth + FYUVLeft, FYUVHeight + FYUVTop);
OffsetRect(Rect, -FMonitor.FRect.Left, -FMonitor.FRect.Top);
//------------------------------
m_lpDDSOffScr.Unlock(nil);
m_lpDDSPrimary.Blt(@Rect, m_lpDDSOffScr, @RectBack, DDBLT_WAIT, nil);

end;


procedure TDDrawItem.Init;
var
lpclip : IDirectDrawClipper;
Ret : HRESULT;
begin

if m_lpDD = nil then

begin

if not FMonitor.FIsDefault then

begin

Ret := DirectDrawCreateEx(@FMonitor.FGUID, m_lpDD, IID_IDirectDraw7, nil);
if Ret <> DD_OK then

begin

ShowMessage(DDErrorString(Ret));
Exit;
end;

end
else

begin

Ret := DirectDrawCreateEx(nil, m_lpDD, IID_IDirectDraw7, nil);
if Ret <> DD_OK then

begin

ShowMessage(DDErrorString(Ret));
Exit;
end;

end;


Ret := m_lpDD.SetCooperativeLevel(Handle, DDSCL_NORMAL);
if Ret <> DD_OK then

begin

ShowMessage(DDErrorString(Ret));
Exit;
end;


//※主表面

ZeroMemory(@m_ddsd, sizeof(DDSURFACEDESC2));
m_ddsd.dwSize := sizeof(DDSURFACEDESC2);
m_ddsd.dwFlags := DDSD_CAPS;
m_ddsd.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE;
//------------------------------
Ret := m_lpDD.CreateSurface(m_ddsd, m_lpDDSPrimary, nil);
if Ret <> DD_OK then

begin

ShowMessage(DDErrorString(Ret));
Exit;
end;


Ret := m_lpDD.CreateClipper(0, lpclip, nil);
if Ret <> DD_OK then

begin

ShowMessage(DDErrorString(Ret));
Exit;
end;

Ret := m_lpDDSPrimary.SetClipper(lpclip);
if Ret <> DD_OK then

begin

ShowMessage(DDErrorString(Ret));
Exit;
end;

lpclip.SetHWnd(0, Handle);
//注意这里
lpclip := nil;
BackSurface();
end;

end;


procedure TDDrawItem.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin

inherited SetBounds(ALeft, ATop, AWidth, AHeight);
FYUVLeft := Trunc(Left / FPanleOnwer.Width * FFormatWidth);
FYUVTop := Trunc(Top / FPanleOnwer.Height * FFormatHeight);
FYUVWidth := Trunc(Width / FPanleOnwer.Width * FFormatWidth);
FYUVHeight := Trunc(Height / FPanleOnwer.Height * FFormatHeight);
end;




end.
 
王锐..在哪都能看到你了....你都成全能了
 
这个你上次给过我,我是想要个TDDrawPanel/TDDrawItem如何创建用法,老兄你搞错了。
我自己动态建了一个TDXDraw可以绘制了,但还有些问题要解决。谢谢帮助!
先结帐,你有空时再说。
 
接受答案了.
 
directx 8以后就M$就不提directdraw了,direct3d取代了这个,可惜问的程序是draw出来的,D3d暂时用不上。使用不淘汰的技术就是这样,问都没人。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
684
import
I
D
回复
0
查看
1K
DelphiTeacher的专栏
D
I
回复
0
查看
579
import
I
后退
顶部