2009-06-05 55 views
0

我想在Delphi 7中使用ChangeDisplaySettingsEx來將特定的監視器設置爲主。 在Windows.pas,它被定義爲在Delphi中使用ChangeDisplaySettingsEx來設置主監視器

function ChangeDisplaySettingsEx(lpszDeviceName: PChar; var lpDevMode: TDeviceMode; 
     wnd: HWND; dwFlags: DWORD; lParam: Pointer): Longint; stdcall; 

MSDN,對ChangeDisplaySettingsEx文檔有LPDEVMODE這樣的評論:「如果LPDEVMODE爲NULL,所有的註冊表值,目前將用於顯示器設置。」

我的目標是改變一個系統上的主顯示器與兩個活動監視器,而不會改變其他任何東西 - 分辨率,位深度等,應該都保持不變。它看起來像傳遞lpDevMode作爲null(nil)是提供的方法來完成此操作。

但是,在Delphi的Windows.pas中,lpDevMode被定義爲打包記錄類型(TDeviceMode),而不是指針類型。顯然,Windows API的Delphi接口執行到Windows API'幕後'使用的指針的轉換。

我打過電話這樣的:

var 
    alldevs : array[0..maxdev] of TDisplayDevice; 
    lpDevMode : pointer; 

begin 
    lpDevMode := nil; 
    lparam := nil; 
    my_hwnd := nil; 

    {... snip....} 

    with alldevs[NewPri] do 
     ChangeDisplaySettingsEx(devicename,TDeviceMode(lpDevMode),my_hwnd,CDS_SET_PRIMARY,lparam); 

這給了我一個無效的類型轉換錯誤的 「TDeviceMode(LPDEVMODE)」。我如何將一個空指針傳遞給ChangeDisplaySettingsEx?還是有更好的方法來做到這一點?

回答

1

你可以嘗試

ChangeDisplaySettingsEx(devicename, PDeviceMode(0)^, my_hwnd, CDS_SET_PRIMARY, 
    lparam); 

它至少在2009年德爾福編譯我不能,雖然測試它。

編輯:

據在網絡上(this is the most detailed I could find)改變主顯示稀缺信息不是一個簡單的過程,因此可能會丟失沿途的步驟。我有兩臺顯示器,但根本不能更換主設備,即使使用控制面板 - 看起來像雙頭顯卡驅動程序也不允許。因此,以下未測試,但也許它會幫助你:

爲了設置你必須遠離首先移動當前的主顯示(0,0)位置的新的主顯示器。這比它需要更棘手,因爲Delphi Windows.pas文件具有不完整的TDeviceMode類型。它是作爲

​​

當它應該改爲

_devicemodeA = record 
    dmDeviceName: array[0..CCHDEVICENAME - 1] of AnsiChar; 
    ... 
    case boolean of 
    FALSE: (
     dmOrientation: SHORT; 
     dmPaperSize: SHORT; 
     dmPaperLength: SHORT; 
     dmPaperWidth: SHORT; 
     dmScale: SHORT; 
     dmCopies: SHORT; 
     dmDefaultSource: SHORT; 
     dmPrintQuality: SHORT; 
    ); 
    TRUE: (
     dmPosition: TPoint; 
     dmDisplayOrientation: DWORD; 
     dmDisplayFixedOutput: DWORD; 
    ); 
    dmColor: SHORT; 
    ... 
end; 

你應該固定記錄類型添加到您的資源,因爲你需要dmPosition調整顯示器的起源。它應該是這樣的:

// get current display settings 
EnumDisplaySettings(PChar(AOldPrimaryDevice), ENUM_REGISTRY_SETTINGS, DevMode1); 
EnumDisplaySettings(PChar(ANewPrimaryDevice), ENUM_REGISTRY_SETTINGS, DevMode2); 

// move old primary display to new position 
DevMode1.dmFields := DM_POSITION; 
DevMode1.dmPosition.x := DevMode2.dmPelsWidth; 
DevMode1.dmPosition.y := 0; 
Win32Check(ChangeDisplaySettingsEx(PChar(AOldPrimaryDevice), DevMode1, 0, 
    CDS_UPDATEREGISTRY or CDS_NORESET, nil)): 

// move old secondary display to (0, 0) and make the primary display 
DevMode2.dmFields := DM_POSITION; 
DevMode2.dmPosition.x := 0; 
DevMode2.dmPosition.y := 0; 
Win32Check(ChangeDisplaySettingsEx(PChar(ANewPrimaryDevice), DevMode2, 0, 
    CDS_SET_PRIMARY or CDS_UPDATEREGISTRY or CDS_NORESET or DM_DISPLAYFLAGS, nil)): 

// magic ??? 
Win32Check(ChangeDisplaySettingsEx(nil, PDeviceMode(0)^, 0, 0, nil)); 
+0

感謝您的建議。這確實編譯,但它並不實際工作。 ChangeDisplaySettingsEx返回0(成功),但主監視器保持不變。 – tim11g 2009-06-05 19:35:01

0

我還沒有證實此事,但是有一個在覆蓋這一點,包括C++代碼MSDN forums後。 「主」監視器是位置0,0處的監視器,因此您需要重新排列監視器的位置以實現此目的。

0

這是我瀏覽Internet上衆多C++和Delphi帖子後的發現。

  • 不想宣佈與工會選擇一個新的TMyDevMode型失蹤領域
  • 利用現有TDevMode類型,但設置與移動缺失的字段()的存儲器複製命令和32位簽名的臨時變量
  • 搬開當前的主從0,0 POS桌面,不適用變更尚未
  • 設置新的當前主桌面到0,0與CDS_SET_PRIMARY標誌,不適用變更尚未
  • xy位置和寬度,高度不應重疊,但它似乎Win7的能自己解決一些問題
  • 與空參數調用ChangeDisplaySettingsEx以應用所有待更改

集dmPosition.x和dmPosition.y值,使用內存偏移:

var dm: TDevMode; 
var tempx, tempy: Integer; 
Move(tempx, dm.dmOrientation, sizeOf(tempx)); 
Move(tempy, dm.dmPaperLength, sizeOf(tempy)); 

獲取dmPosition.x和dmPosition.y值,使用內存偏移量:

var dm: TDevMode; 
var tempx, tempy: Integer; 
Move(dm.dmOrientation, tempx, sizeOf(tempx)); 
Move(dm.dmPaperLength, tempy, sizeOf(tempy)); 

將主要桌面從display1設置爲display2實例。進行更改,然後應用所有未決更改:

flags := CDS_UPDATEREGISTRY or CDS_NORESET; 
ChangeDisplaySettingsEx('\\.\DISPLAY1', devMode1, 0, flags, nil); 
flags := CDS_UPDATEREGISTRY or CDS_SET_PRIMARY or CDS_NORESET; 
ChangeDisplaySettingsEx('\\.\DISPLAY2', devMode2, 0, flags, nil); 
ChangeDisplaySettingsEx(nil, PDeviceMode(0)^, 0, 0, nil); 
相關問題