モニターまたは 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 イベントをキャッチします。