谁有取双显卡的GUID,而创建两个directdraw 表面的程序?(100分)

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

xiaohedou

Unregistered / Unconfirmed
GUEST, unregistred user!
有VC dirctdraw取得双显卡的片段,请帮忙写个delphi试验程序:
GUID g_Guid,g_Mulguid;
//-----------------------------------------------------------------------------
BOOL WINAPI DDEnumCallbackEx( GUID* pGuid, LPTSTR pszDesc, LPTSTR pszDriverName,
OID* pContext, HMONITOR hmon )
{
EnumInfo* pEnumInfo = (EnumInfo*)pContext;

GUID guidNull;
ZeroMemory(&guidNull, sizeof(guidNull));

if (pGuid != NULL &&
g_Guid != guidNull)
g_Mulguid = *pGuid;

if (pGuid != NULL &&
g_Guid == guidNull)
g_Guid = *pGuid;

return TRUE;
// Keep enumerating
}

//-----------------------------------------------------------------------------
// Name: EnumerateScreens()
// Desc: Creates a Screen structure for every appropriate screen in the user's
// computer.
//-----------------------------------------------------------------------------
HRESULT EnumerateScreens()
{
HRESULT hr;
EnumInfo enumInfo;

ZeroMemory( &enumInfo, sizeof(enumInfo) );
enumInfo.bMultimonSupported = TRUE;

if( FAILED( hr = DirectDrawEnumerateEx( DDEnumCallbackEx,
&enumInfo, DDENUM_ATTACHEDSECONDARYDEVICES ) ) )
return hr;

// If something failed inside the enumeration, be sure to return that RESULT
if( FAILED(enumInfo.hr) )
return enumInfo.hr;
return S_OK;
}
在msdn上没有找到DirectDrawEnumerateEx的例子,谢谢了。
 
有报酬吗?
 
如果谈报酬,需要写一个完整的程序
 
我的QQ 87797301
不知你想写一个什么程序
 
很简单的.给你一个我以前用的代码
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;


DirectDrawEnumerateEx(@DDEnumCallbackEx,
nil,
DDENUM_ATTACHEDSECONDARYDEVICES or DDENUM_NONDISPLAYDEVICES
);

调用DirectDrawEnumerateEx就是指定一个回调函数.然后DirectDrawEnumerateEx在枚举的时候直接会调用这个回调函数
 
wr960204:你好,感谢提供支持,我去测试一下。
 
wr960204: TMMonitor没有定义,编译出错。
我的意思是找到两个(多个)显卡的GUID然后分别创建两个(多个)directdraw表面CreateSurfaceEx( guid, w, h, true, true, 0 );供输出文字、图像使用。
 
我晕.TMMonitor是我自己定义的结构.为了记住监视器的.
我给你贴的是我以前的代码.你也不能不改就用啊.
我以前的就是解决多显卡多显示器组成的电视墙的方案用的.
你变通一下啊.
反正就是有多少个显卡就枚举多少次.这个回调函数也就会被调用多少次.函数里面你爱怎么搞就怎么搞
 
是的,我也猜到MM:TMMonitor;是个自定义的结构体,从程序上能看出来。后来,我自己把VC那段程序改为delphi了,如下:
代码:
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;


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

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

    Result := enumInfo.hr;
  Result := DD_OK
end;
wr960204 :很感谢你的帮助,你的代码确实对我帮助很大。结构体的比较你有没有好方法。我的QQ:929638615,希望以后能和多你交流。
 
zlkxzy:不知道你的水平如何?能否一聊,你的QQ我那天没找到。
to ALL:那位能提供根据连个GUID创建surface,并向他们同时输出文字、图像的完整例子,
立即结帖!
 
多显示资源的大概顺序是:
1.首先用EnumerateScreens找到资源GUID
然后DirectDrawCreateEx(guid, lpDD, IID, nil);
2.Set cooperative level
3.Set the display mode
4.Create primary surface (with backbuffer attached if nessery)
lpDD.CreateSurface(sd, lpDDSurface, nil);
 
再给你我以前的代码你参考吧.
我这个代码是枚举监视器.创建一个主表面和一个从表面.表面的格式是YVU格式的.
然后把YUV视频帧拷贝到从表面的显存缓冲区.然后由从表面直接画到主表面.
你要的创建Surface就是这样的.但你要正常画图的话则不要指定YUV格式即可.
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.
 
很感谢wr960204这段时间对我的帮助,你的这段代码已经可以了。DirectDraw:我用DSPACK v2.34编过了,谢谢。
 
后退
顶部