8

私の Delphi-7 アプリケーションには次のように表示されます。

Screen.DesktopWidth  
Screen.DesktopHeight  
Screen.Monitors[0].Width  
Screen.Monitors[0].Height  

また、2 つ目のモニターが選択されている場合は、次のこともできます。

Screen.Monitors[1].Width  
Screen.Monitors[1].Height  

WinXP-Pro PC でアプリケーションを実行した状態で、[コントロール パネル]、[ディスプレイ]、[設定] の順に移動し、2 番目のモニターの設定を変更します (追加または削除)。

次に、[更新] ボタンをクリックして 4 つ (または 6 つ) のパラメーターの新しい値を表示すると、予期しないことが起こります。Screen.DesktopWidth と Screen.DesktopHeight には正しい新しい値が表示されますが、他の 2 つ (または 4) の値が表示されます。パラメータが非常に間違っています。

Screen.Monitors[0].Width = 5586935 のように、 1680 にする必要があります。

Delphi 7 で TScreen を使用するための特別なルールはありますか?

4

3 に答える 3

4

モニターまたは USB ディスプレイ デバイスを接続または切断するときの TScreen のリフレッシュの問題 (バグ) のためにここに来ました。@ Dave82の答えは私にはうまくいきません。関数 MonitorFromWindow の結果は、TScreen オブジェクトの更新を強制するために、別の値 (不明または無効な値) を返す必要があります。

以下のこのチートはトリックを行います:

マルチモンがuses句にあることを確認してください。

uses
 multimon;

これを(フォームの)インターフェイス部分に追加します

protected
procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;

これを(フォームの)実装部分に追加します

    function cheatMonitorFromWindow(hWnd: HWND; dwFlags: DWORD): HMONITOR; stdcall;
    begin
      // Does nothing, returns zero to force invalidate
     Result:=0;
    end;

    procedure TForm1.WMDeviceChange(var Msg: TMessage);
    var
     iCurrDisplayCount    : LongInt;
     iNewDisplayCount     : LongInt;
     pMonitorFromWinProc  : TMonitorFromWindow;

    begin
     iCurrDisplayCount:=Screen.MonitorCount;
     // Force monitor update, fix bug in customform, won't update at display change.
     // This a hack/cheat to multimon MonitorFromWindow func, it's fakes the result.
     // This is required to tell customform.getMonitor() to update the TScreen object.
     pMonitorFromWinProc:=MonitorFromWindow;      // Backup pointer to dynamic assigned DLL func  
     MonitorFromWindow:=cheatMonitorFromWindow;   // Assign cheat func 
     monitor;                                     // call the monitor property that calls customform.getMonitor and cheatfunc
     MonitorFromWindow:=pMonitorFromWinProc;      // restore the original func
     // ==========
     iNewDisplayCount:=Screen.MonitorCount;
     if( iCurrDisplayCount <> iNewDisplayCount ) then
     begin
       // Display count change!
     end;  
end;

customform (Forms.pa 内のコード) 内で何が起こるか?

function TCustomForm.GetMonitor: TMonitor;
var
  HM: HMonitor;
  I: Integer;
begin
  Result := nil;
  HM := MonitorFromWindow(Handle, MONITOR_DEFAULTTONEAREST);
  for I := 0 to Screen.MonitorCount - 1 do
    if Screen.Monitors[I].Handle = HM then
    begin
      Result := Screen.Monitors[I];
      Exit;
    end;

  //if we get here, the Monitors array has changed, so we need to clear and reinitialize it
  for i := 0 to Screen.MonitorCount-1 do
    TMonitor(Screen.FMonitors[i]).Free;
  Screen.FMonitors.Clear;
  EnumDisplayMonitors(0, nil, @EnumMonitorsProc, LongInt(Screen.FMonitors));
  for I := 0 to Screen.MonitorCount - 1 do
    if Screen.Monitors[I].Handle = HM then
    begin
      Result := Screen.Monitors[I];
      Exit;
    end;    
end;

誰かがこれを探しているときに役立つことを願っています。ディスプレイ デバイスの設定の変更 (解像度と向き) を検出する場合は、代わりに WM_DISPLAYCHANGE イベントをキャッチします。

于 2015-09-14T03:23:12.160 に答える
1

プログラムの実行中にユーザーを切り替えると、Screen.Monitors 配列に無効な値が含まれます。次のコード行を使用して、Screen オブジェクトに強制的にリストを更新させます。

Screen.MonitorFromWindow(0, mdNull);
于 2014-08-08T12:35:38.507 に答える
0

TLama のおかげで、Delphi 7 の TScreen 問題の回避策を見つけました。

問題を「引き起こした」元のコード:

LabMon1.Caption := ' Mon 1: ' + IntToStr (Screen.Monitors[0].Width) +
                   ' x ' + IntToStr (Screen.Monitors[0].Height);

if (Screen.MonitorCount = 1)
then LabMon2.Caption := ' Mon 2: -'
else LabMon2.Caption := ' Mon 2: ' + IntToStr (Screen.Monitors[1].Width) +
                        ' x ' + IntToStr (Screen.Monitors[1].Height);

私はそれを解決するためにコードを1行追加するだけでした:

LabMon1.Caption := ' Mon 1: ' + IntToStr (Monitor.Width) +
                   ' x ' + IntToStr (Monitor.Height) ;

LabMon1.Caption := ' Mon 1: ' + IntToStr (Screen.Monitors[0].Width) +
                   ' x ' + IntToStr (Screen.Monitors[0].Height);

if (Screen.MonitorCount = 1)
then LabMon2.Caption := ' Mon 2: -'
else LabMon2.Caption := ' Mon 2: ' + IntToStr (Screen.Monitors[1].Width) +
                        ' x ' + IntToStr (Screen.Monitors[1].Height);

この質問スレッドへの多大な貢献に対して、 再び TLama に感謝します。

于 2012-06-24T12:50:15.483 に答える