Delphi 모니터 화면 해상도 변경 소스

화면의 해상도를 바꾸는 소스 입니다.
대충 만든거라 변수명이나 기타등등이 뭐 좀 그렇습니다.
테스트해본 결과 잘 나옵니다.
pageControl은 DevExpress의 내용을 사용한것이므로 일반 pageControl로 바꾸셔도 됩니다.

해상도를 바꾸는 작업은 3가지 함수만 알면 됩니다.
EnumDisplayDevices, EnumDisplaySettings , ChangeDisplaySettings
위 3가지 함수만 알면 간단합니다.
간단히 제작 방법을 설명합니다.
  1. 우선 EnumDisplayDevices로 설치된 모니터의 종류 및 갯수를 파악 합니다.
  2. EnumDisplaySettings을 이용해서 설치된 모니터의 DeviceName을 이용해서
    각 모니터가 구현가능한 해상도를 얻어 ListBox에 저장합니다.
  3. 사용자가 선택한 해상도를 EnumDisplaySettings와 ChangeDisplaySettings으로 지정하고
    화면의 변화에 따라 사용자의 승인을 얻은뒤 ChangeDisplaySettings(dma,CDS_UPDATEREGISTRY);
    으로 한방에 저장합니다. 뭐 아니면, 원래 해상도로 되돌리면 됩니다.

너무 간단한가요? 뭐 실제로도 간단합니다.
이제 소스 나갑니다. 휘리릭…

unit My_SettingDevice;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, cxControls, cxPC, dxSkinsCore, dxSkinBlack, dxSkinBlue,
  dxSkinCaramel, dxSkinCoffee, dxSkinGlassOceans, dxSkiniMaginary, dxSkinLilian,
  dxSkinLiquidSky, dxSkinLondonLiquidSky, dxSkinMcSkin, dxSkinMoneyTwins,
  dxSkinSilver, dxSkinStardust, dxSkinsDefaultPainters, dxSkinscxPCPainter,
  ExtCtrls, StrUtils;

const
  ENUM_CURRENT_SETTINGS  = $FFFFFFFF; // Word - 1
  ENUM_REGISTRY_SETTINGS = $FFFFFFFE; // Word - 2
type
  TForm3 = class(TForm)
    ListBox1: TListBox;
    Label1: TLabel;
    Button1: TButton;
    cxPageControl1: TcxPageControl;
    Button2: TButton;                 
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var
  dHDC  : HDC;
  dFlag : DWORD;
  DevMode   : TDevMode;
  LoopA : Integer;
  i: Integer;
  Pn : TPanel;
  TS : TcxTabSheet;
  ListBox : TListBox;
  function FormatDevMode( DevMode : TDevMode ) : String ;
  begin
    With DevMode do
    Result := Format( '%d x %d %d bit Colors  %d Hz',
                  [ dmPelsWidth, dmPelsHeight, dmBitsperPel, dmDisplayFrequency ] )  +
                  Ifthen( ((dmPelsWidth * 3 ) Shr 2 ) > dmPelsHeight , ' Wide', '' );
  end;

  Procedure GetAllScreenSize( DeviceName :string; StrList : TStrings ) ;
  var
    DevMode    : TDevMode;
    i : Integer;
  begin
   i := 0;
   DevMode.dmSize := SizeOf( DevMode );
   while EnumDisplaySettings( Pchar( Trim( DeviceName ) ), i, DevMode ) do begin
      StrList.add( FormatDevMode( DevMode ) );//
     Inc( i );
   end;
  end;
  Function GetAllDisplayDevice( StrList : TStrings ) : Integer;
  Var
    DisplayDevice   : TDisplayDevice;
    i : Integer;
  begin
    Result := 0;
    // Display device이름을 알아온다.
    DisplayDevice.cb := SizeOf( DisplayDevice );    // Size를 반드시 넣어야 한다.
    for i := 0 to MaxInt do
    begin
      // 디바이스를 못찾을때 까지 돈다.
      if not EnumDisplayDevices( nil, i , DisplayDevice,  0    ) then break;

      if DisplayDevice.StateFlags <> DISPLAY_DEVICE_MIRRORING_DRIVER then   // Display Device만
        StrList.Add( DisplayDevice.DeviceName + ' : ' +DisplayDevice.DeviceString );
    end;

  end;
begin

  ListBox1.Clear;

  ListBox1.Sorted := True;

  GetAllDisplayDevice( Listbox1.Items );

  // 현재 활성화된 모니터의 갯수를 알아온다.  실제 모니터가 하나여서 체크를 못함. ㅜ.ㅜ
  Caption := 'monitor = ' + inttostr( GetSystemMetrics( SM_CMONITORS ) );

  // PageControl을 모두 지운다.
  While cxPageControl1.PageCount > 0 Do
    cxPageControl1.Pages[ cxPageControl1.PageCount - 1 ].Free;

  // 읽어온 Display Device이름을 알아 온다.
  for i := 0 to ListBox1.Count - 1 do
  begin
    // Page Control을 만든다.
    TS := TcxTabSheet.Create( Self ) ;
    With TS do
    Begin
      Parentfont := true;
      Caption    := ListBox1.Items[i];
      PageControl:= cxPageControl1;
      PageIndex  := cxPageControl1.PageCount - 1;
      PN         := TPanel.Create( TS );
      
      With Pn do
      begin
        Height := 30;
        Align := alTop;
        Parent := TS;

        // 현재 해상도를 얻어 온다.
        DevMode.dmSize := SizeOf( TDevMode );
        EnumDisplaySettings( Pchar( Copy ( ListBox1.Items[i], 1, Pos( ':',ListBox1.Items[i] ) - 2 ) ),
                             ENUM_REGISTRY_SETTINGS, DevMode );
        Caption := FormatDevMode(DevMode );
      end;

      // ListBox를 만들고 현재 가능한 해상도를 얻어온다.
      ListBox := TListBox.Create( TS );
      with ListBox do
      begin
//        Name  := Ts.Caption;
        Parent:= TS;
        Align := alClient;
      end;
      GetAllScreenSize( Pchar( Copy ( ListBox1.Items[i], 1, Pos( ':',ListBox1.Items[i] )- 2 ) ), ListBox.Items );

      TS.Tag           := ListBox.Items.IndexOf( Pn.Caption );
      ListBox.ItemIndex:= TS.tag;
    end;
  end;

end;

procedure TForm3.Button2Click(Sender: TObject);
var
  dma            : TDeviceModeA;
  DeviceName     : string;
  i, inxScreenResize,
  iResult        : Integer;
begin
  // 해상도 변경..
//  ListBox1.Items[ cxPageControl1.ActivePageIndex ] // 현재 디바이스..
  dma.dmSize := SizeOf( TDeviceModeA );

  for i := 0 to cxPageControl1.ActivePage.ComponentCount - 1 do
    If cxPageControl1.ActivePage.Components[i] is TListBox Then
    begin
      inxScreenResize := TlistBox( cxPageControl1.ActivePage.Components[i] ).ItemIndex;
      break;
    end;
  DeviceName := Copy ( ListBox1.Items[ cxPageControl1.ActivePageIndex ], 1, Pos( ':',ListBox1.Items[i] )- 2 );
  if EnumDisplaySettings( pchar( DeviceName ),
                          inxScreenResize ,
                          dma ) then
  begin
    iResult := ChangeDisplaySettings( dma, CDS_FULLSCREEN );

    if iResult = DISP_CHANGE_SUCCESSFUL then
    begin

      if (MessageDlg('설정 사항을 저장하시겠습니까?', mtWarning, [mbOK, mbCancel], 0) = mrOK ) then
      begin
        ChangeDisplaySettings( dma, CDS_UPDATEREGISTRY );
        Button1.Click;
      end
      else
      begin
        EnumDisplaySettings( pchar( DeviceName ), cxPageControl1.ActivePage.Tag , dma );
        ChangeDisplaySettings( dma, CDS_FULLSCREEN );
      end;

    end;

  end;

end;

end.
;

 

Author: yyjksw