1

ショートストーリー

ゲームはフルスクリーンで開始されますが、フルスクリーンの directX ウィンドウです。ゲームはウィンドウをサポートしていますが、手動で行う必要があります。Delphi で、境界線とキャプションなしで(システム全体のホットキーを使用して)画面に合わせてウィンドウを拡大/サイズ変更するプログラムを作成したため、フルスクリーンのように見えますが、ハードウェアへの直接アクセスはトリガーされません。ハードウェアへの直接アクセスで使用されるトリックをサポートしていない DisplayLink アダプターを使用しているが、醜い境界線なしでフルスクリーンで再生したいので、これは重要です。全画面表示の DirectX ウィンドウ以外の任意のウィンドウのサイズを変更できます。手動で全画面表示モードをウィンドウ表示に変更する必要があります。これを自動化したいのです。

長い話(質問を知りたい場合は下にスクロールしてください)

コンピューターから 5 メートル離れた場所に TV 画面を備えた DisplayLink アダプターがあります。ソファからゲームをプレイできるように、それを使用してゲームを実行したいと考えています。ただし、ほとんどのゲームはデスクトップ ウィンドウ マネージャー (DWM) をバイパスして、フル スクリーン時にグラフィックス ハードウェアに直接アクセスするため、DisplayLink ドライバーはほとんどのゲームをフル スクリーンで再生できません。

これは、DisplayLink の一般的な既知の問題です。ウィンドウ モードでは、アダプターは非常にうまく機能するので、Delphi で小さなプログラムを作成して、ウィンドウを最大化して全画面表示にするのではなく、ウィンドウを全画面表示にする代わりに、ウィンドウを全画面表示にすることを考えました。

私が作成したプログラムはかなりうまく動作しますが、directx 画面が既にウィンドウ化されている場合にのみ機能します (ゲームはフルスクリーンで開始されるため、ウィンドウ化するにはウィンドウ化されたアイコンを 1 回クリックする必要があります)。ゲームには、起動時にウィンドウを表示するオプションが既にありますが、固定解像度の可能性は低くなります。フルスクリーンで起動したときにこのプロセスを自動化したい。directx画面をウィンドウ表示に変更したいのですが、この後、最大化せずにフルスクリーンにサイズ変更/ストレッチします。

プログラムの仕組み

プログラムは、システム全体のキーボード ホットキーを定義します。ホットキーを押すと、プログラムはアクティブなフォアグラウンド ウィンドウ (windows API getForeGroundWindow()) をフルスクリーンに引き伸ばして最大化し、ボーダーレス ウィンドウにしてフルスクリーンのように見せます。これにより、システムのメイン画面だけでなく、好きな画面でゲームを実行することもできます。ホットキーをもう一度押すと、ウィンドウは以前の状態 (トグル) に戻ります。「パッチ」を適用する前に、ウィンドウの種類もチェックするため、サイズ変更できないウィンドウでは使用できません。

質問

フルスクリーンに拡大/サイズ変更する必要があるウィンドウのハンドルを知っています。フルスクリーンの 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