2006. május 31., szerda

How to retrieve and change display settings


Problem/Question/Abstract:

I can't find a way to enumerate or test display frequencies. When I use ChangeDisplaySettings to test for a given mode it returns DISP_CHANGE_SUCCESSFUL, no matter what I put in for dmDisplayFrequency. Should I just attempt to set a good median freq such as 75Hz and forget about it? Any other ideas?

Answer:

type
  PdmArray = ^TDmArray;
  TDmArray = array[0..0] of TDeviceMode;

  TForm1 = class(TForm)
    { ... }
  private
    lpDmArray: PDmArray;
    NumModes: integer;
    BitsPerPixel: DWord;
    RefreshRate: DWord;
    CurrentDisplayMode: integer;
    SelectedDisplayMode: integer;
    { ... }
  public
  end;

procedure TForm1.RetrieveDisplayModes;
var
  I: Integer;
  MoreModes: Bool;
  dm: TDeviceMode;
begin
  StringGridDisplayModes.ColCount := 5;
  StringGridDisplayModes.RowCount := 2;
  StringGridDisplayModes.Cells[0, 0] := 'Mode';
  StringGridDisplayModes.Cells[1, 0] := 'Resulution';
  StringGridDisplayModes.Cells[2, 0] := 'Bits per Pixel (Colors)';
  StringGridDisplayModes.Cells[3, 0] := 'DisplayFrequency';
  StringGridDisplayModes.Cells[4, 0] := 'DeviceName';
  for I := 0 to StringGridDisplayModes.ColCount do
    StringGridDisplayModes.Cells[I, 1] := '';
  MoreModes := TRUE;
  I := 0;
  while MoreModes do
  begin
    MoreModes := EnumDisplaySettings(nil, I, dm);
    StringGridDisplayModes.Cells[0, StringGridDisplayModes.RowCount - 1] :=
      IntToStr(I);
    StringGridDisplayModes.Cells[1, StringGridDisplayModes.RowCount - 1] :=
      IntToStr(dm.dmPelsWidth) + ' * ' + IntToStr(dm.dmPelsHeight);
    StringGridDisplayModes.Cells[2, StringGridDisplayModes.RowCount - 1] :=
      IntToStr(dm.dmBitsPerPel);
    StringGridDisplayModes.Cells[3, StringGridDisplayModes.RowCount - 1] :=
      IntToStr(dm.dmDisplayFrequency);
    StringGridDisplayModes.Cells[4, StringGridDisplayModes.RowCount - 1] :=
      dm.dmDeviceName;
    if (dm.dmPelsWidth = Screen.Width) and (dm.dmPelsHeight = Screen.Height) and
      (dm.dmBitsPerPel = BitsPerPixel) and (dm.dmDisplayFrequency = RefreshRate) then
      CurrentDisplayMode := I;
    StringGridDisplayModes.RowCount := StringGridDisplayModes.RowCount + 1;
    Inc(i);
  end;
  StringGridDisplayModes.RowCount := StringGridDisplayModes.RowCount - 1;
  NumModes := I;
  GetMem(lpDmArray, sizeof(TDeviceMode) * NumModes);
  FillChar(lpDmArray^, sizeof(TDeviceMode) * NumModes, #0);

{$IFOPT R+}
{$DEFINE CKRANGE}
{$R-}
{$ENDIF}

  for I := 0 to (NumModes - 1) do
    EnumDisplaySettings(nil, I, lpDmArray[i]);

{$IFDEF CKRANGE}
{$UNDEF CKRANGE}
{$R+}
{$ENDIF}

end;

procedure TForm1.ButtonRetrieveDisplayModesClick(Sender: TObject);
begin
  RetrieveDisplayModes;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  try
    FreeMem(lpDmArray, sizeof(TDeviceMode) * NumModes);
  except
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  DC: hDC;
begin
  DC := GetDC(0);
  BitsPerPixel := GetDeviceCaps(DC, BITSPIXEL);
  RefreshRate := GetDeviceCaps(DC, VREFRESH);
  ReleaseDC(0, DC);
  StatusBar.Panels[2].Text := 'Resolution: ' + IntToStr(Screen.Width) + ' * ' +
    IntToStr(Screen.Height)
    + ', ColorDept: ' + IntToStr(BitsPerPixel) + ', RefreshRate: '
    + IntToStr(RefreshRate);
  ButtonRetrieveDisplayModesClick(Sender);
end;

procedure Tform1.SetDisplayMode(Mode: integer);
var
  ReturnVal: LongInt;
begin

{$IFOPT R+}
{$DEFINE CKRANGE}
{$R-}
{$ENDIF}

  ReturnVal := ChangeDisplaySettings(lpDmArray[Mode], CDS_UPDATEREGISTRY);

{$IFDEF CKRANGE}
{$UNDEF CKRANGE}
{$R+}
{$ENDIF}

  if ReturnVal <> DISP_CHANGE_SUCCESSFUL then
    case ReturnVal of
      DISP_CHANGE_SUCCESSFUL: ShowMessage('DISP_CHANGE_SUCCESSFUL');
      DISP_CHANGE_RESTART: ShowMessage('DISP_CHANGE_RESTART');
      DISP_CHANGE_BADFLAGS: ShowMessage('DISP_CHANGE_BADFLAGS');
      DISP_CHANGE_FAILED: ShowMessage('DISP_CHANGE_FAILED');
      DISP_CHANGE_BADMODE: ShowMessage('DISP_CHANGE_BADMODE');
      DISP_CHANGE_NOTUPDATED: ShowMessage('DISP_CHANGE_NOTUPDATED');
    end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése