Rotating displays programmatically in Windows XP? (C++/Qt and WindowsAPI)

↘锁芯ラ 提交于 2019-12-04 04:58:06

问题


So, essentially, we're writing a service-level application that can alter attributes of various user-level settings. I'm working on the display portion right now.

We've gotten it to work for the version of our software for Windows 7, and almost everything works with the exception of rotating the displays in Windows XP (which, curiously, DOES work in Windows 7). The "ChangeDisplaySettingsEX" function in the Windows API provided by Microsoft is returning the return code for a bad display mode (DISP_CHANGE_BADMODE), so I tried applying the flag to allow "unsafe" display modes (because I'm a rebel. Yeah I'll try unsafe display modes, watch out: we're dealing with a bad**s here). Applying that flag caused the function to return the bad flags parameter (DISP_CHANGE_BADFLAGS).

Upon further investigation, there is apparently no way native to Windows XP to rotate a display. We COULD, however, find a way to do it, but it was through a separate driver provided by Intel (IEGD). To me, this means two things: the first is that there isn't a way to do this even NON-programmatically through Windows, nor is there a way to do it using Windows API calls. The second is that if Intel found a way to program a driver to do it, there must be SOME way to do it.

I'll put some code below, sorry this is kind of tl;dr. The tl;dr version could simply be the title of the post, I suppose...

...

    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);
                }
            }

We apply the settings below:

     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;

So the code at the bottom in particular isn't written particularly elegantly, but that was because we were trying to get a handle on how to do it before we cleaned it up.

So, does anyone have any idea how to do rotate the displays in this manner for Windows XP?


回答1:


The whole Display and Monitor thing in XP isn't as clear cut as they are in WDDM. While you can enumerate monitors "attached" to a display, you can't change the mode of the monitor by calling ChangeDisplaySettingsEx. To change the display mode, you call CDSE with the display, e.g. "\\.\Display1" or something like that. I spent a good chunk of time playing with these functions on XP in a previous life and I don't think you can do what you want to do with them.

As far as I know, screen rotation is an implemention detail of the display driver under XP, and there is no standard way to do this from user space. Some Intel drivers list portrait modes when you call EnumDisplaySettings. By setting your display to one of these modes, you end up with a rotated screen.

In short, there is no standard way to do this for all graphics card vendors. But you maybe able to do the same thing their utility apps do to achieve the effect.

Under Windows 7, rotation and mirroring is provided by the OS. This link should give you the details of how things work under Win7. There isn't a equivalent things for XP I'm afraid.



来源:https://stackoverflow.com/questions/9625057/rotating-displays-programmatically-in-windows-xp-c-qt-and-windowsapi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!