请教如何实现旋转当前所有窗口及桌面任意角度?
如把桌面旋转到180度或95度,并且桌面上的图标,可以正常使用?
如把当前所有的窗口旋转到180度或95度,并且可以正常操作?

解决方案 »

  1.   

    提供一些思路:1.創建不规则窗口再旋转,可藏窗口,只显示位图,旋转之;
    2.建立一个当前窗口的兼容BITMAP,旋转BITMAP,接受BITMAP的输入消息,传递到窗口;
    3.用CRgn,或者重載一些類,如:CWnd ,CFramWnd, CDialog, CButton ,CMenu, CEdit;
    4.可以考虑directX...
      

  2.   

    听说 ChangeDisplaySettingsEx 可以实现,听说而已,我也没用过
      

  3.   

    方法一:新建一個工程,刪掉裡面的Unit1.pas和Unit1.dfm,然後將下面兩段代碼分別保存為Unit1.pas和Unit1.dfm。
    將下面的代碼保存成Unit1.pas:
    代碼:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        btnCounterClockwise90Degree: TButton;
        btnRevert: TButton;
        btnClockwise90Degree: TButton;
        btnClockwise180Degree: TButton;
        procedure btnCounterClockwise90DegreeClick(Sender: TObject);
        procedure btnRevertClick(Sender: TObject);
        procedure btnClockwise90DegreeClick(Sender: TObject);
        procedure btnClockwise180DegreeClick(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}const
      ENUM_CURRENT_SETTINGS = DWORD(-1);
      DMDO_DEFAULT = 0;
      DMDO_90 = 1;
      DMDO_180 = 2;
      DMDO_270 = 3;type
      PDeviceMode = ^TDeviceMode;
      TDeviceMode = packed record
        dmDeviceName: array[0..CCHDEVICENAME - 1] of AnsiChar;
        dmSpecVersion: Word;
        dmDriverVersion: Word;
        dmSize: Word;
        dmDriverExtra: Word;
        dmFields: DWORD;
        dmPosition: TPointL;
        dmDisplayOrientation: DWORD;
        dmDisplayFixedOutput: DWORD;
        dmColor: SHORT;
        dmDuplex: SHORT;
        dmYResolution: SHORT;
        dmTTOption: SHORT;
        dmCollate: SHORT;
        dmFormName: array[0..CCHFORMNAME - 1] of AnsiChar;
        dmLogPixels: Word;
        dmBitsPerPel: DWORD;
        dmPelsWidth: DWORD;
        dmPelsHeight: DWORD;
        dmDisplayFlags: DWORD;
        dmDisplayFrequency: DWORD;
        dmICMMethod: DWORD;
        dmICMIntent: DWORD;
        dmMediaType: DWORD;
        dmDitherType: DWORD;
        dmICCManufacturer: DWORD;
        dmICCModel: DWORD;
        dmPanningWidth: DWORD;
        dmPanningHeight: DWORD;
      end;function ChangeDisplaySettings(lpDevMode: PDeviceMode; dwFlags: DWORD): Longint;
      stdcall; external user32 name 'ChangeDisplaySettingsA';
    function EnumDisplaySettings(lpszDeviceName: PChar; iModeNum: DWORD;
      lpDevMode: PDeviceMode): BOOL; stdcall; external user32 name 'EnumDisplaySettingsA';
    procedure TForm1.btnCounterClockwise90DegreeClick(Sender: TObject);
    var
      dm: TDeviceMode;
      dwTemp: DWORD;
    begin
      ZeroMemory(@dm, SizeOf(dm));
      dm.dmSize := SizeOf(dm);
      if (EnumDisplaySettings(nil, ENUM_CURRENT_SETTINGS, @dm)) then
      begin
        if dm.dmDisplayOrientation <> DMDO_90 then
        begin
          if dm.dmDisplayOrientation in [DMDO_DEFAULT, DMDO_180] then
          begin
            dwTemp := dm.dmPelsHeight;
            dm.dmPelsHeight := dm.dmPelsWidth;
            dm.dmPelsWidth := dwTemp;
          end;
          dm.dmDisplayOrientation := DMDO_90;
          ChangeDisplaySettings(@dm, 0);
        end;
      end;
    end;procedure TForm1.btnRevertClick(Sender: TObject);
    var
      dm: TDeviceMode;
      dwTemp: DWORD;
    begin
      ZeroMemory(@dm, SizeOf(dm));
      dm.dmSize := SizeOf(dm);
      if (EnumDisplaySettings(nil, ENUM_CURRENT_SETTINGS, @dm)) then
      begin
        if dm.dmDisplayOrientation <> DMDO_DEFAULT then
        begin
          if dm.dmDisplayOrientation in [DMDO_90, DMDO_270] then
          begin
            dwTemp := dm.dmPelsHeight;
            dm.dmPelsHeight := dm.dmPelsWidth;
            dm.dmPelsWidth := dwTemp;
          end;
          dm.dmDisplayOrientation := DMDO_DEFAULT;
          ChangeDisplaySettings(@dm, 0);
        end;
      end;
    end;procedure TForm1.btnClockwise90DegreeClick(Sender: TObject);
    var
      dm: TDeviceMode;
      dwTemp: DWORD;
    begin
      ZeroMemory(@dm, SizeOf(dm));
      dm.dmSize := SizeOf(dm);
      if (EnumDisplaySettings(nil, ENUM_CURRENT_SETTINGS, @dm)) then
      begin
        if dm.dmDisplayOrientation <> DMDO_270 then
        begin
          if dm.dmDisplayOrientation in [DMDO_DEFAULT, DMDO_180] then
          begin
            dwTemp := dm.dmPelsHeight;
            dm.dmPelsHeight := dm.dmPelsWidth;
            dm.dmPelsWidth := dwTemp;
          end;
          dm.dmDisplayOrientation := DMDO_270;
          ChangeDisplaySettings(@dm, 0);
        end;
      end;
    end;procedure TForm1.btnClockwise180DegreeClick(Sender: TObject);
    var
      dm: TDeviceMode;
      dwTemp: DWORD;
    begin
      ZeroMemory(@dm, SizeOf(dm));
      dm.dmSize := SizeOf(dm);
      if (EnumDisplaySettings(nil, ENUM_CURRENT_SETTINGS, @dm)) then
      begin
        if dm.dmDisplayOrientation <> DMDO_180 then
        begin
          if dm.dmDisplayOrientation in [DMDO_90, DMDO_270] then
          begin
            dwTemp := dm.dmPelsHeight;
            dm.dmPelsHeight := dm.dmPelsWidth;
            dm.dmPelsWidth := dwTemp;
          end;
          dm.dmDisplayOrientation := DMDO_180;
          ChangeDisplaySettings(@dm, 0);
        end;
      end;
    end;end.
     将下面的代码保存成Unit1.dfm:代码: object Form1: TForm1
      Left = 456
      Top = 309
      BorderStyle = bsDialog
      Caption = 'Form1'
      ClientHeight = 141
      ClientWidth = 204
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -12
      Font.Name = 'Simsun'
      Font.Style = []
      OldCreateOrder = False
      Position = poScreenCenter
      PixelsPerInch = 96
      TextHeight = 12
      object btnCounterClockwise90Degree: TButton
        Left = 8
        Top = 8
        Width = 185
        Height = 25
        Caption = '90'#176#24320#22987#33756#21333#22312#21491#36793
        TabOrder = 0
        OnClick = btnCounterClockwise90DegreeClick
      end
      object btnRevert: TButton
        Left = 8
        Top = 104
        Width = 185
        Height = 25
        Caption = #36824#21407
        TabOrder = 3
        OnClick = btnRevertClick
      end
      object btnClockwise90Degree: TButton
        Left = 8
        Top = 40
        Width = 185
        Height = 25
        Caption = '90'#176' '#24320#22987#33756#21333#22312#24038#36793
        TabOrder = 1
        OnClick = btnClockwise90DegreeClick
      end
      object btnClockwise180Degree: TButton
        Left = 8
        Top = 72
        Width = 185
        Height = 25
        Caption = '180'#176' '#26059#36716#65292#19978#19979#39072#20498
        TabOrder = 2
        OnClick = btnClockwise180DegreeClick
      end
    end 
      

  4.   

    http://www.cnblogs.com/sea918/archive/2010/03/22/1691763.html方法二:使用ChangeDisplaySettingsEx,可以參考這篇貼子:
      

  5.   

    LS的哥:這個網址裡是介紹SCREEN ROTATION的ChangeDisplaySettingsEx函數的中文實例
      

  6.   

    http://www.cnblogs.com/sea918/archive/2010/03/22/1691763.html
    以上介紹的是screen rotation的例子...
      

  7.   

    function ChangeDisplaySettingsEx(lpszDeviceName: PChar; var lpDevMode: TDeviceMode;        wnd: HWND; dwFlags: DWORD; lParam: Pointer): Longint; stdcall;In MSDN, the documentation for ChangeDisplaySettingsEx has the following comment for lpDevMode: "If lpDevMode is NULL, all the values currently in the registry will be used for the display setting."My objective is to change the Primary monitor on a system with two active monitors, without changing anything else - resolution, bit depth, etc, should all remain the same. It seems like passing lpDevMode as null (nil) is the method that is provided to accomplish this.However, lpDevMode is defined as a packed record type (TDeviceMode), not a pointer type, in Delphi's Windows.pas. Apparently, the Delphi interface to the Windows API performs the translation to the pointers used by Windows API 'behind the scenes'.I tried calling it like this: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);
     
    You could tryChangeDisplaySettingsEx(devicename, PDeviceMode(0)^, my_hwnd, CDS_SET_PRIMARY,  lparam);
    it does at least compile on Delphi 2009. I can't test it though.
    Edit:
    According to the scarce information on the net (this is the most detailed I could find) changing the primary display isn't a simple process, so you may be missing a step along the way. I have two monitors, but can't change the primary device at all, not even with the control panel - looks like the dual-head display card driver doesn't allow it. The following therefore isn't tested, but maybe it will help you:
    In order to set a new primary display you have to move the current primary display away from the (0, 0) position first. This is more tricky than it needs to be, because the Delphi Windows.pas file has an incomplete TDeviceMode type. It is given as
    _devicemodeA = record  dmDeviceName: array[0..CCHDEVICENAME - 1] of AnsiChar;  ...  dmOrientation: SHORT;  dmPaperSize: SHORT;  dmPaperLength: SHORT;  dmPaperWidth: SHORT;  dmScale: SHORT;  dmCopies: SHORT;  dmDefaultSource: SHORT;  dmPrintQuality: SHORT;  dmColor: SHORT;  ...end;
    when it should instead be
    _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;
    You should add the fixed record type to your sources, as you need dmPosition to adjust the origin of the displays. It should go something like this:
    // get current display settingsEnumDisplaySettings(PChar(AOldPrimaryDevice), ENUM_REGISTRY_SETTINGS, DevMode1);EnumDisplaySettings(PChar(ANewPrimaryDevice), ENUM_REGISTRY_SETTINGS, DevMode2);// move old primary display to new positionDevMode1.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 displayDevMode2.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));
      

  8.   

    我用BETA部的高端電腦測試沒有問題你一定要確認以下事項:确认硬件或地层驱动支持吗?可通过该函数查询的。我也用过,发现不支持。不过不少lcd屏可通过跳线方法,实现屏幕翻转.....
    .............
    旋转屏幕90度ChangeDisplaySettingsEx实例——WinCE2010年03月14日 星期日 20:07        DEVMODE DevMode;
            memset(&DevMode, 0, sizeof (DevMode));
            DevMode.dmSize               = sizeof (DevMode);
            DevMode.dmFields             = DM_DISPLAYORIENTATION;
            
            if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_TEST, NULL))
            {
                RETAILMSG(1, (L"ChangeDisplaySettingsEx failed to get the supported rotation angles (error=%d).\n", GetLastError()));
            }
            else
            {
                if(DevMode.dmDisplayOrientation == 0)
                {    
                    DevMode.dmDisplayOrientation 
     .........
      

  9.   

    ...
    任务栏的窗口类名是:ShellTrayWnd。      
    开始按钮的窗口类名是:Button。      
    应用程序切换区的窗口类名是:ReBarWindow32。      
    任务栏通知区的窗口类名是:TrayNotifyWnd。      
    任务栏时钟的窗口类名是:TrayClockWClass。      
    (2)调用FindWindow函数得到任务栏的窗口句柄。      
    (3)调用FindWindowEx函数得到任务栏各子区域的窗口句柄。      
    (4)根据窗口句柄,调用ShowWindow函数控制任务栏各区域显示或隐藏...
      

  10.   

    其實使用ChangeDisplaySettingsEx函數是可以搞定的,只是需要多多研究而已那麼試著用API的方法將statubutton的(任務欄旋轉180後的位置改變,先hide原的,先出現在新的位置)當然只是一個拋磚引玉的小動作
    ShowWindow(FindWindowEx(FindWindow('Shell_TrayWnd', nil), 0, 'Button', nil), SW_HIDE); 
    Windows.SetParent(FindWindowEx(FindWindow('Shell_TrayWnd', nil), 0, 'Button', nil), GetDesktopWindow);