1

短篇故事

游戏是全屏启动的,但它是一个全屏的 directX 窗口。游戏支持窗口化,但我必须手动操作。我在 Delphi 中制作了一个程序,可以拉伸/调整任何窗口的大小以适应屏幕(使用系统范围的热键),没有边框和标题,因此它看起来像全屏,但不会触发直接硬件访问。这很重要,因为我使用的 DisplayLink 适配器不支持直接硬件访问所使用的技巧,但希望全屏播放而没有丑陋的边框。我可以调整除全屏 DirectX 窗口之外的任何窗口的大小,我必须手动将全屏模式更改为窗口化,这就是我想要自动化的。

长篇大论(如果您想知道问题,请向下滚动)

我有一个 DisplayLink 适配器,它的电视屏幕距离我的电脑 5 米。我想用它来运行游戏,这样我就可以在沙发上玩游戏了。然而,DisplayLink 驱动程序无法全屏播放大多数游戏,因为大多数游戏在全屏时会绕过桌面窗口管理器 (DWM) 直接访问图形硬件。

这是 DisplayLink 的常见/已知问题。在窗口模式下,适配器性能非常好,所以我想在 Delphi 中编写一个小程序,将窗口化的 Directx 屏幕最大化到全屏,而不是通过最大化它来全屏,而是将窗口拉伸到全屏。

我制作的程序运行得很好,但是只有当directx屏幕已经窗口化时(游戏开始全屏,所以我必须单击窗口图标使其窗口化)。该游戏已经有一个选项可以在启动时使其窗口化,但固定分辨率的可能性较小。我想在全屏启动时自动化这个过程。我想将directx屏幕更改为窗口化,然后将其调整大小/拉伸到全屏而不最大化它。

程序如何运作

该程序定义了一个系统范围的键盘热键。当按下热键时,程序getForeGroundWindow()通过将其拉伸到全屏来最大化任何活动的前台窗口(windows API)并使其成为无边框窗口,因此它看起来像全屏。这使您还可以在您喜欢的任何屏幕上运行游戏,而不仅仅是在系统的主屏幕上。再次按下热键时,窗口将返回到之前的状态(切换)。在应用“补丁”之前,它还会检查窗口的类型,因此它不能用于不可调整大小的窗口。

问题

我知道必须将窗口的句柄拉伸/调整为全屏。当它是全屏 DirectX 窗口时,除非它是窗口化的,否则我无法做任何事情。如何通过向此窗口句柄 ( sendMessage()) 发送消息将其状态更改为窗口化。这可能吗?

一些代码(让您了解幕后发生的事情)

function TWinSpread.setWindowStyleBounds( h : hWnd; lStyle : LongInt = 0; pR : PRect = nil ) : LongInt;
var
 bRestore : Boolean;
 r        : TRect;
 pMouse   : TPoint;
 rStyle   : TStyleStruct;

begin
 Result:=0;
 if( h <= 0 ) then
  Exit;

 bRestore:=( lStyle > 0 );
 if( NOT bRestore ) then
 begin
  lStyle:=getWindowLong( h, GWL_STYLE );
  Result:=lStyle;
  lStyle:=lStyle and not WS_BORDER and not WS_SIZEBOX and not WS_DLGFRAME;

  if( Assigned( pR )) then
   begin
    r:=pR^;
   end
  else begin
        getWindowRect( h, r );
        r:=getDisplayRect( getDisplayNumFromPoint( Point( r.left+2, r.top+2 ) ) );
      end;
 end
 else begin
       Result:=lStyle;
      end;

 rStyle.styleOld:=Result;
 rStyle.styleNew:=lStyle;
 if( Result = lStyle ) then
  begin
   rStyle.styleOld:=getWindowLong( h, GWL_STYLE );
  end;

 sendMessage( h, WM_ENTERSIZEMOVE, 0, 0 );
 __restoreWindow( h );
 setWindowLong( h, GWL_STYLE, lStyle );

 if( NOT bRestore ) then
 begin
   setWindowPos( h, HWND_TOP, r.left,r.top,r.right-r.left,r.bottom-r.top, SWP_FRAMECHANGED and WS_SIZEBOX );
   moveWindow( h, r.left,r.top,r.right-r.left,r.bottom-r.top, TRUE );
   sendMessage( h, WM_SIZE, SIZE_RESTORED, makeLong( r.right-r.left,r.bottom-r.top ));
 end
 else begin
       // updateWindowFrame( h );
       setWindowPos( h, 0, 0,0,0,0, SWP_FRAMECHANGED or SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOOWNERZORDER );
       getWindowRect( h, r );
      end;

 sendMessage( h, WM_EXITSIZEMOVE, 0, 0 );
 sendMessage( h, WM_STYLECHANGED, GWL_STYLE, longInt( Pointer( @rStyle )));

 activateWindow( h );
 windows.setFocus( h );

 if( __mousePresent() ) then
 begin
  pMouse:=__getMousePos();

   // Simulate click to focus window
  __setMousePos( Point( r.left+2, r.top+2 ));
  mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
  mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

   // restore mouse
  __setMousePos( pMouse );
 end;

end;

procedure TWinSpread.shHotKeyHotKey(Sender: TObject; Index: Integer);
var
 h : hWnd;
 sHandle  : string;
 lStyle   : LongInt;
 bNoBorder : Boolean;

begin
 h:=getForeGroundWindow();
 if( h <= 0 ) then
  exit;

 if( h = handle ) then
  begin
   showMessage( 'It works!' );
   exit;
  end;

 sHandle:=ItoA( h );
 if( scWinStyles.Count > 0 ) then
  begin
   lStyle:=AtoI( scWinStyles.list.Values[sHandle] );
   if( lStyle > 0 ) then
    begin
     scWinStyles.list.delete( scWinStyles.list.IndexOfName(sHandle));
     setWindowStyleBounds( h, lStyle );
     Exit;
    end;
  end;

 bNoBorder:=windowIsBorderless( h ); 
 if( isMaximized( h ) or bNoBorder ) then
 begin
  // does not work for ActiveX fullscreen window :-(
  //if( bNoBorder ) then
  // setWindowSizeable( h, TRUE );
  __maximizeWindow( h );
  __restoreWindow( h );
  showWindow( h, SW_SHOWNORMAL );
 end;

 if( windowIsSizeable( h ) ) then
 begin
  lStyle:=setWindowStyleBounds( h );
  scWinStyles.list.Values[sHandle]:=ItoA( lStyle );
 end
 else Windows.Beep( 600, 200 );
end;

一些截图

一些截图

注意:图中有错字,ActiveX 必须是 DirectX ;-)

有关 DisplayLink 问题的更多信息:http: //support.displaylink.com/knowledgebase/articles/543922-games-do-not-work-on-windows-with-displaylink-soft

4

0 回答 0