精英盒子 -> 程序设计 -> Win7全屏修复工具-源码分析和解答贴 [打印本页]

jybox 2011-07-31 20:58

Win7全屏修复工具-源码分析和解答贴

软件介绍和下载地址:http://jybox.net/soft/win7full/
有任何关于源代码和开发的疑问可以在这里提问
关于本手册的错误,欢迎指出



该手册版本:2011.7.31第一版            对应程序版本2011.7.26第一版



该程序是通过修改注册表的方式来修复全屏的,具体思路来自网络上流传的方法,确实已经找不到最早的作者了,原文摘录如下



一、Windows7下游戏全屏问题通用解决方法(推荐使用):


Win键+R键,打开运行窗口,输入regedit 回车,这样就打开了注册表编辑器,然后,定位到以下位置:


HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\GraphicsDrivers\Configuration\


在Configuration这上面右键,选择查找,输入Scaling,在右框找到scaling,右键scaling修改
将数值改为3即可(原值是4),这种方法基本通杀所有Windows7下游戏的全屏问题。


例如,有的用户找到了:


HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\GraphicsDrivers\Configuration\ BNQ7820G5904027026_14_07D9_0D^982BE6B19D3412E0FED7CFC9082CBA39\00\00\Scaling


把此处的Scaling数值改为3即可,在这个例子中,BNQ7820G5904027026_14_07D9_0D^982BE6B19D3412E0FED7CFC9082CBA39
注意,这段数值由于显示设备的不同而改变,以大家自己搜索到的键值为准!!




从这个思路来看,只要能够正确读写注册表即可。但其中还有一个难点,就是其中的一项的值是不固定的。


该程序使用Qt Creator 2.0.1的QT GUI程序向导构建,基于QWidget
有很多向导自动生成的代码,在此不做说明!


先来看UI布局:
也是使用Qt Creator的工具制作的:
[attachment=1]

可以看出,布局是相当简单的,只有一个QLabel和两个按钮


然后是部分核心代码:
注,我写的并不完美,欢迎大家提供更好的方法
  1. //widget.cpp
    /*
    by精英王子
    2011.7.26
    */
    #include "widget.h"
    #include "ui_widget.h"
    #include <QSettings>
    #include <QMessageBox>
    #include <QStringList>
    #include <QTextCodec>
    #include <QDesktopWidget>
    Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
    {
        ui->setupUi(this);
        
        QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));
        this->setWindowTitle(tr("Win7全屏去黑条"));
        
        QDesktopWidget* desktop = QApplication::desktop();
        move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2);
    }
    Widget::~Widget()
    {
        delete ui;
    }
    void Widget::on_pushButton_clicked()
    {
        try{
            QSettings *reg = new QSettings("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\GraphicsDrivers\\Configuration",QSettings::NativeFormat);
            QStringList keys = reg->allKeys();
            QString s,a;
            if(keys.size()==0)
            {
                throw keys;
            }
            s=keys[1];
            a=s.left(s.indexOf("/"));
            delete reg;
            reg = new QSettings("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\GraphicsDrivers\\Configuration\\"+a+"\\00\\00",QSettings::NativeFormat);
            reg->setValue("Scaling",3);
            if(reg->value("Scaling").toInt()==3)
            {
                QMessageBox::information(0,0,tr("修改成功"));
            }
            else
            {
                throw reg;
            }
            delete reg;
        }
        catch(...)
        {
            QMessageBox::information(0,0,tr("出现了一个错误,请确认您正在使用的是Win7系统,同时已经以管理员权限运行本程序!"));
        }
    }
    void Widget::on_pushButton_2_clicked()
    {
        system("start http://jybox.net");
    }


下面是对于源码的解析:(解释在源码之后)
  1. Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
    {
        ui->setupUi(this);
            
        QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));
        this->setWindowTitle(tr("Win7全屏去黑条"));
            
        QDesktopWidget* desktop = QApplication::desktop();
        move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2);
    }


在构造函数中,先是第3行初始化界面,当然,这是向导自动生成的。
然后第5行设置默认字符集,我习惯于对于所有涉及编码的东西都使用utf8.当然,具体设置成什么要取决于你的文件的编码
第6行设置窗口标题
第8-9行设置窗口默认居中
  1. Widget::~Widget()
    {
         delete ui;
    }
析构函数,不解释
  1. void Widget::on_pushButton_clicked()
    {
        try{
            //.........
        }
        catch(...)
        {
            QMessageBox::information(0,0,tr("出现了一个错误,请确认您正在使用的是Win7系统,同时已经以管理员权限运行本程序!"));
        }
    }

然后是“一键消除黑条”的按钮的事件。为了捕捉错误,这里使用了try-catch,catch(...)可以捕捉所有类型的错误。


如上面的思路,我们先要得到那个随机的键名
  1. QSettings *reg = new QSettings("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\GraphicsDrivers\\Configuration",QSettings::NativeFormat);
    QStringList keys = reg->allKeys();
    QString s,a;
    if(keys.size()==0)
    {
          throw keys;
    }
第1行创建了一个QSetting对象,该类用于操作系统无关的持久性的数据储存,在Win下,对应的就是注册表
首先定位到包含这个不确定键的父项
然后第2行声明一个QStringList对象,其实按我理解QStringList就是一个字符串数组,然后取得reg的所有子健(包括非间接子),赋给keys
第4-7行检查是否获得了子键(如果用xp系统的话就得不到子键),如果没有得到,则抛出异常

第3行声明了两个QString,s用于保存其中一个子键,a用于保存那个不确定键的名字

  1. s=keys[1];
    a=s.left(s.indexOf("/"));
经过我的实际测试,这个不确定键的父项所包含的非间接子键都是属于这个不确定键的。
所以只要获得其中一个子键的前面部分即可得到这个不确定键的名字
上面的两行代码正是实现了这个功能,结果被保存在a中
  1. delete reg;
    reg = new QSettings("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\GraphicsDrivers\\Configuration\\"+a+"\\00\\00",QSettings::NativeFormat);
    reg->setValue("Scaling",3);
第1行先销毁reg,因为它已经没用了,而且它是个指针
第2行重新构造QSetting对象,这次就直接得到了要修改的Scaling的父键了。
第3行把Scaling的值设置为我们需要的3
  1. [color=#008ef1]if(reg->value("Scaling").toInt()==3)[/color]
    {
         QMessageBox::information(0,0,tr("修改成功"));
    }
        else
    {
         throw reg;
    }
这几行代码判断了Scaling是否已经被修改成了我们需要的3.如果成功则提示用户,不成功(没以管理员权限运行的时候会失败)则抛出异常
  1. delete reg;
最后销毁reg
  1. void Widget::on_pushButton_2_clicked()
    {
        system("start http://jybox.net");
    }

这是"访问我们的网站"按钮的相应事件
直接使用system函数来打开网址,这个函数不是QT的,是标准库提供的


好了,到这里源码分析就结束了,关于源码的任何问题可以直接跟帖提问
过于复杂的问题也可以单独开帖

对于非开发人员的使用问题,请来这个贴询问:http://jybox.net/bbs/read.php?tid-22.html
(对于不同的人群,说话的深度也不一样嘛!)


abreto 2011-07-31 22:17
前排围观

jybox 2011-08-01 00:03
技术区不能灌水

abreto 2011-08-01 03:12
不是灌水




Powered by phpwind v8.7 Code ©2003-2011 phpwind
Time 0.046757 second(s),query:5 Gzip enabled