關於MFC中全屏顯示及空間放縮

今天終於解決全屏顯示是空間超出的問題,

問題出在: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的屬性要設置爲有最大化最小化的按鈕的按鈕欄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章