在Windows XP中以编程方式旋转显示? (C ++ / Qt和WindowsAPI)

时间:2012-03-08 21:16:27

标签: c++ qt winapi windows-xp

因此,基本上,我们正在编写一个可以改变各种用户级设置属性的服务级应用程序。我现在在显示部分工作。

我们已经将它用于我们的Windows 7软件版本,除了在Windows XP中旋转显示器外,几乎所有功能都有效(奇怪的是,它们可以在Windows 7中运行)。 Microsoft提供的Windows API中的“ChangeDisplaySettingsEX”函数返回错误显示模式(DISP_CHANGE_BADMODE)的返回代码,因此我尝试应用该标志以允许“不安全”的显示模式(因为我是反叛者。是的我'尝试不安全的显示模式,注意:我们在这里处理一个坏的问题)。应用该标志导致函数返回坏标志参数(DISP_CHANGE_BADFLAGS)。

经过进一步调查,Windows XP显然没有办法旋转显示器。但是,我们可以找到一种方法,但它是通过英特尔(IEGD)提供的单独驱动程序实现的。对我来说,这意味着两件事:第一件事就是没有办法通过Windows无法以编程方式执行此操作,也没有办法使用Windows API调用来实现。第二,如果英特尔找到了一种方法来对驱动程序进行编程,那么必须有一些方法可以做到这一点。

我会在下面放一些代码,抱歉这有点儿;博士。 tl; dr版本可能只是帖子的标题,我想......

...

    else if( key == "Rotation" ) {
                QString rotationsStr = value.toString();
                QStringList rotations = rotationsStr.split(",", QString::SkipEmptyParts);

                for( int i = 0; i < currentLayout.size(); i++){
                    WinMon tempMon = currentLayout.at(i);

                    DWORD dwTemp = tempMon.dm.dmPelsHeight;
                    if(rotations.size() > 1) {
                        switch( rotations.at(i).toInt(&ok, 10) )
                        {
                        case 0:     // Rotate 0 degrees

                            tempMon.dm.dmFields = DM_DISPLAYORIENTATION;
                            if(currentLayout.at(i).dm.dmDisplayOrientation == DMDO_90 ||
                               currentLayout.at(i).dm.dmDisplayOrientation == DMDO_270){
                                tempMon.dm.dmPelsHeight= tempMon.dm.dmPelsWidth;
                                tempMon.dm.dmPelsWidth = dwTemp;
                                tempMon.dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
                            }
                            tempMon.dm.dmDisplayOrientation = DMDO_DEFAULT;
                            break;

                        case 1:     // Rotate 90 degrees

                            tempMon.dm.dmFields = DM_DISPLAYORIENTATION;
                            if(currentLayout.at(i).dm.dmDisplayOrientation == DMDO_DEFAULT ||
                               currentLayout.at(i).dm.dmDisplayOrientation == DMDO_180){
                                tempMon.dm.dmPelsHeight= tempMon.dm.dmPelsWidth;
                                tempMon.dm.dmPelsWidth = dwTemp;
                                tempMon.dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
                            }
                            tempMon.dm.dmDisplayOrientation = DMDO_90;
                            break;

                        case 2:     // Rotate 180 degrees

                            tempMon.dm.dmFields = DM_DISPLAYORIENTATION;
                            if(currentLayout.at(i).dm.dmDisplayOrientation == DMDO_90 ||
                               currentLayout.at(i).dm.dmDisplayOrientation == DMDO_270){
                                tempMon.dm.dmPelsHeight= tempMon.dm.dmPelsWidth;
                                tempMon.dm.dmPelsWidth = dwTemp;
                                tempMon.dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
                            }
                            tempMon.dm.dmDisplayOrientation = DMDO_180;
                            break;

                        case 3:     // Rotate 270 degrees

                            tempMon.dm.dmFields = DM_DISPLAYORIENTATION;
                            if(currentLayout.at(i).dm.dmDisplayOrientation == DMDO_DEFAULT ||
                               currentLayout.at(i).dm.dmDisplayOrientation == DMDO_180){
                                tempMon.dm.dmPelsHeight= tempMon.dm.dmPelsWidth;
                                tempMon.dm.dmPelsWidth = dwTemp;
                                tempMon.dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
                            }
                            tempMon.dm.dmDisplayOrientation = DMDO_270;
                            break;

                        }
                    }

                    else
                    {
                        switch( rotations.at(0).toInt(&ok, 10) ) {

                        case 0:     // Rotate 0 degrees

                            tempMon.dm.dmFields = DM_DISPLAYORIENTATION;
                            if(currentLayout.at(i).dm.dmDisplayOrientation == DMDO_90 ||
                               currentLayout.at(i).dm.dmDisplayOrientation == DMDO_270){
                                tempMon.dm.dmPelsHeight= tempMon.dm.dmPelsWidth;
                                tempMon.dm.dmPelsWidth = dwTemp;
                                tempMon.dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
                            }
                            tempMon.dm.dmDisplayOrientation = DMDO_DEFAULT;
                            break;

                        case 1:     // Rotate 90 degrees

                            tempMon.dm.dmFields = DM_DISPLAYORIENTATION;
                            if(currentLayout.at(i).dm.dmDisplayOrientation == DMDO_DEFAULT ||
                               currentLayout.at(i).dm.dmDisplayOrientation == DMDO_180){
                                tempMon.dm.dmPelsHeight= tempMon.dm.dmPelsWidth;
                                tempMon.dm.dmPelsWidth = dwTemp;
                                tempMon.dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
                            }
                            tempMon.dm.dmDisplayOrientation = DMDO_90;
                            break;

                        case 2:     // Rotate 180 degrees

                            tempMon.dm.dmFields = DM_DISPLAYORIENTATION;
                            if(currentLayout.at(i).dm.dmDisplayOrientation == DMDO_90 ||
                               currentLayout.at(i).dm.dmDisplayOrientation == DMDO_270){
                                tempMon.dm.dmPelsHeight= tempMon.dm.dmPelsWidth;
                                tempMon.dm.dmPelsWidth = dwTemp;
                                tempMon.dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
                            }
                            tempMon.dm.dmDisplayOrientation = DMDO_180;
                            break;

                        case 3:     // Rotate 270 degrees

                            tempMon.dm.dmFields = DM_DISPLAYORIENTATION;
                            if(currentLayout.at(i).dm.dmDisplayOrientation == DMDO_DEFAULT ||
                               currentLayout.at(i).dm.dmDisplayOrientation == DMDO_180){
                                tempMon.dm.dmPelsHeight = tempMon.dm.dmPelsWidth;
                                tempMon.dm.dmPelsWidth = dwTemp;
                                tempMon.dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
                            }
                            tempMon.dm.dmDisplayOrientation = DMDO_270;
                            break;
                        }
                    }

                    currentLayout.replace(i, tempMon);
                }
            }

我们应用以下设置:

     long returnCode;

    for( int i=0; i < currentLayout.size(); i++ ){
        WinMon myMon = currentLayout.at(i);

        returnCode = ChangeDisplaySettingsEx(myMon.name.utf16(),(DEVMODE*)&(myMon.dm), NULL, CDS_UPDATEREGISTRY|CDS_NORESET, NULL);
        if( returnCode != DISP_CHANGE_SUCCESSFUL )
        {
            qWarning() << "Failed to change display " << i;
            qWarning() << "Return Code:  " << returnCode;

            qWarning() << " ";
            qWarning() << "DISP_CHANGE_SUCCESSFUL  : " << DISP_CHANGE_SUCCESSFUL;
            qWarning() << "DISP_CHANGE_BADDUALVIEW : " << DISP_CHANGE_BADDUALVIEW;
            qWarning() << "DISP_CHANGE_BADFLAGS    : " << DISP_CHANGE_BADFLAGS;
            qWarning() << "DISP_CHANGE_BADMODE     : " << DISP_CHANGE_BADMODE;
            qWarning() << "DISP_CHANGE_BADPARAM    : " << DISP_CHANGE_BADPARAM;
            qWarning() << "DISP_CHANGE_FAILED      : " << DISP_CHANGE_FAILED;
            qWarning() << "DISP_CHANGE_NOTUPDATED  : " << DISP_CHANGE_NOTUPDATED;
            qWarning() << "DISP_CHANGE_RESTART     : " << DISP_CHANGE_RESTART;
            qWarning() << " ";
            qWarning() << "Again, your return value was: " << returnCode;
            return false;
        }
    }

    ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
    return true;

所以特别是底部的代码并没有特别优雅地编写,但那是因为我们在清理之前试图了解如何操作。

那么,有没有人知道如何以这种方式为Windows XP旋转显示器?

1 个答案:

答案 0 :(得分:2)

XP中的整个显示和监视器并不像WDDM那样明确。虽然您可以枚举“附加”到显示器的监视器,但您无法通过调用ChangeDisplaySettingsEx来更改监视器的模式。要更改显示模式,请使用显示屏调用CDSE,例如“\\。\ Display1”或类似的东西。我花了很多时间在以前的生活中使用XP上的这些功能,我认为你不能做你想做的事情。

据我所知,屏幕旋转是XP下显示驱动程序的实现细节,没有标准的方法可以从用户空间执行此操作。调用EnumDisplaySettings时,某些Intel驱动程序会列出纵向模式。通过将显示器设置为这些模式之一,您最终会旋转屏幕。

简而言之,对于所有图形卡供应商而言,没有标准的方法可以做到这一点。但是你可能会做他们的实用程序应用程序做同样的事情来实现这种效果。

在Windows 7下,操作系统提供旋转和镜像。 This link应该为您提供Win7下工作原理的详细信息。 XP恐怕没有相同的东西。