关于MFC中全屏显示及空间放缩

    技术2022-05-19  30

    今天终于解决全屏显示是空间超出的问题,

    问题出在: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的属性要设置为有最大化最小化的按钮的按钮栏


    最新回复(0)