在MFC中使dialog自适应缩放

起因

最近用mfc做了不少小软件,界面上都是基于CDialog或者CFormView,界面不能缩放一直是问题。一个办法是在OnSize()里面调用所有控件的MoveWindow()函数,根据比例调整控件大小。但是在界面上控件比较多的时候,这个发放就显得很繁琐了。于是我写了一个CAutoResize类,去实现控件的统一缩放。

工作原理

原理上很简单,对于MFC中的CDilalog,它的信息都存在程序文件夹下的XXX.rc中,XXX是项目名称。如下图所示,

CAutoResize类首先就读取XXX.rc,先获取控件长宽信息,dlgWidth和dlgHeight。然后获取相应控件上的ID,x和y坐标,控件宽度和高度,用这些值去除以dlgWidth和dlgHeight得到相应的比例,然后把信息存在Vector数组中。

Init函数

  1 bool CAutoResize::Init(char *resourceName, char *dlgID)
  2 {
  3     CString strRcName;
  4     CString strDlgID;
  5     strDlgID.Format("%s", dlgID);
  6     strRcName.Format("./%s", resourceName);
  7 
  8     if(!rcFile.Open(strRcName, CFile::modeRead))
  9     {
 10         AfxMessageBox("can't open the resource file");
 11     }
 12     CString strRead;
 13 
 14 //找到dlgID所在的行
 15 
 16     while(rcFile.ReadString(strRead))
 17     {
 18         TRACE("strRead:%s
", strRead);
 19 
 20         if(!Match(strRead, strDlgID))
 21         {
 22             continue;
 23         }
 24         else 
 25         {   
 26             int commaIndex = strRead.Find(",");
 27             strRead = strRead.Mid(commaIndex + 1);
 28             commaIndex = strRead.Find(",");
 29             strRead = strRead.Mid(commaIndex + 1);
 30             commaIndex = strRead.Find(",");
 31             dlgWidth = atoi((const char*)strRead.Left(commaIndex));
 32             strRead = strRead.Mid(commaIndex + 1);
 33             dlgHeight = atoi((const char*)strRead);
 34             TRACE("dlgWidth:%d
dlgHeight:%d
", dlgWidth, dlgHeight);
 35 
 36 
 37             for(int i=0;i<3;i++)
 38             {
 39                 rcFile.ReadString(strRead);
 40 
 41             }
 42             break;
 43         }
 44     }
 45 
 46 
 47     // 开始读取各个控件的信息
 48     while(rcFile.ReadString(strRead))
 49     {
 50         Item item;  
 51 
 52 
 53         TRACE("strRead:%s
", strRead);
 54         if(strRead == "END")
 55         {
 56             break;
 57         }
 58         CString str = strRead.Left(20);
 59         str.TrimLeft(" ");
 60         str.TrimRight(" ");
 61         TRACE("begin to store items
");
 62         strRead = strRead.Mid(20);
 63         strRead.TrimLeft(" ");
 64 
 65 
 66         CString tempRead, strTemp;
 67         tempRead.Empty();
 68         strTemp.Empty();
 69         long pos;
 70 
 71         do 
 72         {
 73         tempRead.TrimLeft(" ");
 74         strRead = strRead + tempRead;
 75          pos = rcFile.GetPosition();
 76 
 77         rcFile.ReadString(tempRead);
 78         TRACE("tempRead:%s
", tempRead);
 79         strTemp = tempRead.Left(20);
 80         strTemp.TrimLeft(" ");
 81         strTemp.TrimRight(" ");
 82 
 83         TRACE("strTemp:%s
", strTemp);
 84 
 85         }while(strTemp.IsEmpty());
 86 
 87 
 88         rcFile.Seek(pos, CFile::begin);
 89 
 90         TRACE("strRead:%s
", strRead);     
 91 
 92         TRACE("str:%s
", str);
 93 
 94 //不同的控件类型格式不同,分情况讨论
 95 //  format: ID, x, y, width, height, style
 96         if(str == _T("EDITTEXT") || str == _T("COMBOBOX"))   
 97         {
 98             int commaIndex = strRead.Find(",");
 99  //存储控件id 类型CString, 过会还要读取resource.h去获取对应的Int类型id
100             item.itemID = strRead.Left(commaIndex);              
101             TRACE("itemID:%s
", strRead.Left(commaIndex));
102             strRead = strRead.Mid(commaIndex + 1);
103             commaIndex = strRead.Find(",");
104  // 坐标x比例
105 
106             item.xPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgWidth;  
107             strRead = strRead.Mid(commaIndex + 1);
108             commaIndex = strRead.Find(",");
109 // 坐标y比例
110             item.yPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgHeight; 
111             strRead = strRead.Mid(commaIndex + 1);
112             commaIndex = strRead.Find(",");
113 // 宽比例
114             item.widthPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgWidth;  
115             strRead = strRead.Mid(commaIndex + 1);
116 //高比例
117             item.heightPercentage = (float)atoi((const char *)strRead) / (float)dlgHeight;          
118 
119 
120         }      
121  // format: text, id, class, style, x, y, width, height
122         else if(str == _T("CONTROL"))                     
123         {
124             int commaIndex = strRead.Find(",");
125             strRead = strRead.Mid(commaIndex + 1);          
126             commaIndex = strRead.Find(",");
127             item.itemID = strRead.Left(commaIndex);
128             TRACE("itemID:%s
", strRead.Left(commaIndex));
129             strRead = strRead.Mid(commaIndex + 1);
130             commaIndex = strRead.Find(",");
131             strRead = strRead.Mid(commaIndex + 1);
132             commaIndex = strRead.Find(",");
133             strRead = strRead.Mid(commaIndex + 1);
134             commaIndex = strRead.Find(",");
135             item.xPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgWidth;
136 
137             strRead = strRead.Mid(commaIndex + 1);
138             commaIndex = strRead.Find(",");
139             item.yPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgHeight;
140             strRead = strRead.Mid(commaIndex + 1);
141             commaIndex = strRead.Find(",");
142             item.widthPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgWidth;
143             strRead = strRead.Mid(commaIndex + 1);
144 
145             item.heightPercentage = (float)atoi((const char *)strRead) / (float)dlgHeight;
146 
147 
148 
149         }       
150 // format :text, id, x, y, width, height
151         else                                                           
152         {
153             TRACE("others
");
154             int commaIndex = strRead.Find(",");
155             strRead = strRead.Mid(commaIndex + 1);      
156             commaIndex = strRead.Find(",");
157             item.itemID = strRead.Left(commaIndex);
158             TRACE("itemID:%s
", strRead.Left(commaIndex));
159             strRead = strRead.Mid(commaIndex + 1);
160             commaIndex = strRead.Find(",");
161             item.xPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgWidth;
162 
163             strRead = strRead.Mid(commaIndex + 1);
164             commaIndex = strRead.Find(",");
165             item.yPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgHeight;
166             strRead = strRead.Mid(commaIndex + 1);
167             commaIndex = strRead.Find(",");
168             item.widthPercentage = (float)atoi((const char *)strRead.Left(commaIndex)) / (float)dlgWidth;
169             strRead = strRead.Mid(commaIndex + 1);
170 
171             item.heightPercentage = (float)atoi((const char *)strRead) / (float)dlgHeight;
172 
173 
174 
175 
176         }   
177 
178         TRACE("%s %f %f %f %f
", item.itemID, item.xPercentage, item.yPercentage, item.widthPercentage, item.heightPercentage);
179         itemVec.push_back(item);
180         TRACE("num of cotrol object is :%d", itemVec.size());
181 
182     }
183 
184     return true;
185 }

GetIdFromString函数,读取resource.h获取对应Int类型id。

 1 int CAutoResize::GetIdFromString(CString &str)   // Convert the type of control's ID from string to int.
 2 {
 3 
 4     CStdioFile file;
 5     int len = str.GetLength();
 6     if(!file.Open(_T("./resource.h"), CFile::modeRead)) // read the resource file
 7     {
 8         AfxMessageBox(_T("resource file open failed"));
 9         return 0;
10     }
11     CString strRead;
12     while(file.ReadString(strRead))
13     {
14         if(!strRead.IsEmpty())
15         {
16             if(strRead.Left(2) == "#d")
17             {   
18                 strRead = strRead.Mid(8);
19                 int commaIndex = strRead.Find(" ");
20 
21                 if(strRead.Left(commaIndex) == str)                     
22                 {
23                     strRead = strRead.Mid(commaIndex+1);
24                     strRead.TrimLeft(" ");
25                     TRACE("%s
", strRead);
26                     return atoi((const char*)strRead);   // get  item id;
27                 }
28             }
29         }
30     }
31     return 0;
32 }

Resize函数 改变控件大小

 1 void CAutoResize::Resize(CView *pView, int cx, int cy)
 2 {
 3 
 4     //从vector中取出每个控件信息
 5     std::vector<Item>::iterator iter;
 6     for(iter = itemVec.begin(); iter != itemVec.end();++iter)  
 7     {   
 8         Item *item = static_cast<Item*>(iter);
 9         int x = item->xPercentage*cx;
10         int y = item->yPercentage*cy;
11         int width = item->widthPercentage*cx;
12         int height = item->heightPercentage*cy;
13         CRect rc;
14         rc.SetRect(x, y, x+width, y+height);
15         TRACE("cotrol name:%s
", item->itemID);
16         TRACE("	 x:%d, y:%d,  %d, height:%d
", x, y, width, height);
17         int id = GetIdFromString(item->itemID);
18 
19         // MoveWindow
20 
21         if(id)
22         {       
23         (pView->GetDlgItem(id))->MoveWindow(&rc);
24         }
25     }
26 }

使用方法

1.在CDialog类中加入CAutoSize类的成员变量

2.在对话框的初始化函数中调用Init函数,传入资源文件名和对话框id

3.在OnSize()中调用Resize函数。

注:对话框中必须给每个CStatic控件不同的id,不然就不能改变大小。

不足之处

1.一些控件类型格式不同,目前init函数里所测试过的格式不多,不排除有一些格式读不出来。所以这个类只是提供一种方法,并不通用。

2.由于运行时需要读取XXX.rc和resource.h文件,所以在生成的exe运行文件文件夹下也必须要有这两个文件。

 

原文地址:https://www.cnblogs.com/wangke1020/p/3527958.html