今天终于解决全屏显示是空间超出的问题,
问题出在:1) 对话框内部控件static frame 超出了对话框的大小;
2) 对话框的属性栏中中的 最大化最小化按钮,没有的话会影响:双击时不响应最大化,全屏时覆盖任务栏;
3) 在算倍率ratio时,float xratio = (float)GetSystemMetrics(SM_CXFULLSCREEN)/XSCREEN;XSCREEN影响缩小时的对话框大小;
下面是源代码解释:
过程的起始是在WM_ONSIZE消息中:
------->当PaintTime == 0时:
if(PaintTime == 0) { PaintTime++; CRect rc1; GetClientRect(&rc1); //get the Dialog point left,top(0,0) WindowWidth=rc1.Width(); WindwoHeight=rc1.Height(); CRect rc2=rc1; ClientToScreen(&rc2); // transfer client point to screen xOffset=rc2.left-rc1.left; // the distance between client X yOffset=rc2.top-rc1.top;
i=0; EnumChildWindows(this->GetSafeHwnd(),EnumWindowsProc,0); //Enumerate the child controls in the client ShowWindow(SW_SHOWMAXIMIZED); }
其中EnumChildWindows()中有回调函数EnumWIndowsProc()
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { if(i>=MAX_CONTROL_NUM) return FALSE;
CRect rc; ::GetWindowRect(hwnd,&rc); rc.left -= xOffset; rc.right -= xOffset; rc.top -= yOffset; rc.bottom -= yOffset; s[i].xs1=(double)rc.left/(double)WindowWidth; //首次对空间大小的比例进行设置 s[i].ys1=(double)rc.top/(double)WindwoHeight; s[i].xs2=(double)rc.Width()/(double)WindowWidth; s[i].ys2=(double)rc.Height()/(double)WindwoHeight; i++; return TRUE; }
------->当PaintTime == 1时:
CRect rc1; GetClientRect(&rc1); WindowWidth=rc1.Width(); WindwoHeight=rc1.Height(); ClientToScreen(&rc1); if (PaintTime == 1) { PaintTime++; float xratio = (float)GetSystemMetrics(SM_CXFULLSCREEN)/1280; //Set the ratio in this screen resolution float yratio = (float)GetSystemMetrics(SM_CYFULLSCREEN)/904; ratio = 2.0*min(xratio,yratio); m_graph.SetRatio(ratio); //for the nagetive class if need oriwidth = WindowWidth; oriheight = WindwoHeight; }
i=0; EnumChildWindows(this->GetSafeHwnd(),SetWindowRectProc,0); InvalidateRect(0);
其中 InvalidateRect(0);无效矩形被标记后,是否重画,
又用到了另一个枚举子窗口的回调函数 SetWindowRectProc():
代码如下:
BOOL CALLBACK SetWindowRectProc(HWND hwnd, long lParam) { if(i>=MAX_CONTROL_NUM) return FALSE;
CRect rc; rc.left=WindowWidth*s[i].xs1; rc.top=WindwoHeight*s[i].ys1; rc.right=WindowWidth*s[i].xs1+WindowWidth*s[i].xs2; rc.bottom=WindwoHeight*s[i].ys1+WindwoHeight*s[i].ys2; ::MoveWindow(hwnd,rc.left,rc.top,rc.Width(),rc.Height(),1); i++; return TRUE; }
此时控件窗口乘以相应的放大缩小scare,就使得控件的大小发生变化。
------->当PaintTime == 2时:
也就不是第一次启动软件时窗口发生变化:在双击边框触发的边框变化
if(PaintTime == 2)
{ ratio = ratio*(min(WindowWidth/oriwidth,WindwoHeight/oriheight)); m_graph.SetRatio(ratio); oriwidth = WindowWidth; oriheight = WindwoHeight; } i=0; EnumChildWindows(this->GetSafeHwnd(),SetWindowRectProc,0); InvalidateRect(0);
也就是整个工作流程就是,在PaintTime== 0时,记录每个控件相对于Client内部的相对位置,记录在s[i].xs中,s[i]中保存了四个量
struct scale { double xs1; // client left_top ,X double ys1; // client left_top, Y double xs2; // client width double ys2; // client height };
有这四个量,就可以定位(Left_top)后,width and height 相应的左右大小比例
然后得到对话框client的rc的顶点,宽,高,* scare,便可以保持控件在dialog中的相对位置不变。
下面为较完整代码,可移植:
/*****************************************************************************/ // 下面的代码使得控件随着窗口的变化而变化
#define MAX_CONTROL_NUM 100 //设置支持的最大控件数 struct scale { double xs1; double ys1; double xs2; double ys2; }; scale s[MAX_CONTROL_NUM]; int WindowWidth; int WindwoHeight; int xOffset; int yOffset; int i=0; int PaintTime=0;
float ratio; float oriwidth; float oriheight;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { if(i>=MAX_CONTROL_NUM) return FALSE;
CRect rc; ::GetWindowRect(hwnd,&rc); rc.left -= xOffset; rc.right -= xOffset; rc.top -= yOffset; rc.bottom -= yOffset; s[i].xs1=(double)rc.left/(double)WindowWidth; s[i].ys1=(double)rc.top/(double)WindwoHeight; s[i].xs2=(double)rc.Width()/(double)WindowWidth; s[i].ys2=(double)rc.Height()/(double)WindwoHeight; i++; return TRUE; }
BOOL CALLBACK SetWindowRectProc(HWND hwnd, long lParam) { if(i>=MAX_CONTROL_NUM) return FALSE;
CRect rc; rc.left=WindowWidth*s[i].xs1; rc.top=WindwoHeight*s[i].ys1; rc.right=WindowWidth*s[i].xs1+WindowWidth*s[i].xs2; rc.bottom=WindwoHeight*s[i].ys1+WindwoHeight*s[i].ys2; ::MoveWindow(hwnd,rc.left,rc.top,rc.Width(),rc.Height(),1); i++; return TRUE; }
void CPsdWalkingDlg::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy);
if(bRun) { if(PaintTime == 0) { PaintTime++; CRect rc1; GetClientRect(&rc1); WindowWidth=rc1.Width(); WindwoHeight=rc1.Height(); CRect rc2=rc1; ClientToScreen(&rc2); xOffset=rc2.left-rc1.left; yOffset=rc2.top-rc1.top;
i=0; EnumChildWindows(this->GetSafeHwnd(),EnumWindowsProc,0); ShowWindow(SW_SHOWMAXIMIZED); } else { CRect rc1; GetClientRect(&rc1); WindowWidth=rc1.Width(); WindwoHeight=rc1.Height(); ClientToScreen(&rc1); if (PaintTime == 1) { PaintTime++; float xratio = (float)GetSystemMetrics(SM_CXFULLSCREEN)/1280; float yratio = (float)GetSystemMetrics(SM_CYFULLSCREEN)/904; ratio = 2.0*min(xratio,yratio); m_graph.SetRatio(ratio); oriwidth = WindowWidth; oriheight = WindwoHeight; } else { ratio = ratio*(min(WindowWidth/oriwidth,WindwoHeight/oriheight)); m_graph.SetRatio(ratio); oriwidth = WindowWidth; oriheight = WindwoHeight; } i=0; EnumChildWindows(this->GetSafeHwnd(),SetWindowRectProc,0); InvalidateRect(0); } } } /***************************************************************************************/
还有dialog的属性要设置为有最大化最小化的按钮的按钮栏