今天終於解決全屏顯示是空間超出的問題,
問題出在: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的屬性要設置爲有最大化最小化的按鈕的按鈕欄