zoukankan      html  css  js  c++  java
  • VC一些经验系列:《平均绘画矩形图,双击全屏》

    1.RGB宏报错

    RGB宏是这样的,

    #define RGB(r,g,b)          ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))

    但是penBlack.CreatePen(PS_SOLID, 3, #ff0000); 在有的文件中可以用,有的文件中会报错【error C2064: 项不会计算为接受 1 个参数的函数】

       我猜应该是编译器,包含的括号运算有一定的限制导致的。

    所以改成((COLORREF)(((255)|((WORD)((0))<<8))|(((DWORD)(0))<<16)));  //(BYTE) 删除就可以了


                //draw rectangle
                dc.SelectStockObject(NULL_BRUSH); //不使用画刷

                CPen penBlack;

        //penBlack.CreatePen(PS_SOLID, 3, #ff0000);
                COLORREF crColor = ((COLORREF)(((255)|((WORD)((0))<<8))|(((DWORD)(0))<<16)));
                penBlack.CreatePen(PS_SOLID, 3, crColor);


                CPen* pOldPen = dc.SelectObject(&penBlack);
                dc.Rectangle(CRect(WndRect.left -2,WndRect.top -2, WndRect.right+1,WndRect.bottom+1));

    2.  给出窗口的总数,计算每行要画多少窗口

    //计算每行窗口的个数  //1 4 9 16 32 64 128 256
       float fMaxWndNumOfRow = sqrt((float)nNumOfLVWnd);
       long nTemp = fMaxWndNumOfRow;
       int nMaxWndNumOfRow = fMaxWndNumOfRow>nTemp?nTemp+1:nTemp;

    3. 得到每行的窗口数量之后,就可以按照比例 1*1 ,  2*2, 3*3, 4*4, 5*5, 6*6,来画图了

      1 void CMainDialog::DeployLiveViewWnds(int nNumOfLVWnd)   //just Comment关于画图,最好用float---doubel 因为更精确
      2 {OutputDebugString(L"enter DeployLiveViewWnds");
      3 
      4    this->Invalidate();//reflash windows first
      5 
      6    nTotalWnd = nNumOfLVWnd;
      7 
      8 
      9    //计算每行窗口的个数  //1 4 9 16 32 64 128 256
     10    float fMaxWndNumOfRow = sqrt((float)nNumOfLVWnd);
     11    long nTemp = fMaxWndNumOfRow;
     12    int nMaxWndNumOfRow = fMaxWndNumOfRow>nTemp?nTemp+1:nTemp;
     13 
     14    
     15 
     16 
     17    int   i(0), nRow(0), nCol(0), nTempNumOfLVWnd(0);
     18    int   nLVWndWidth(0), nLVWndHeight(0);
     19    int   nNextX(0), nNextY(0), nNextWidth(0), nNextHeight(0);
     20    CRect rectClient;
     21    this->GetClientRect(rectClient);
     22 
     23 
     24    //==============
     25    //just 位移 让  右 和 下 都有足够的位置画完矩形,普通场合 右和下  会少一个像素
     26    rectClient.bottom = rectClient.bottom -2;
     27    rectClient.right =  rectClient.right -2;
     28    //==============
     29 
     30 
     31    // Get the width and height of live view window
     32    TCHAR temp[200];
     33    wsprintf(temp, L"CMainDialog::DeployLiveViewWnds ()  主窗口 left=%d, top=%d, right=%d, bottom=%d , ",rectClient.left, rectClient.top, rectClient.right, rectClient.bottom);
     34    OutputDebugString(temp);
     35 
     36    //bottom = 600
     37    //right = 800
     38 
     39 
     40    //1280  720
     41    //640-1   310-1
     42 
     43 
     44    //800* 600
     45    //400-1*300-1
     46    //if 1windows      0,    0, 400-1, 300-1
     47    //if 2windows    400,    0, 400-1, 300-1
     48    //if 3windows      0,  300, 400-1, 300-1
     49    //if 4windows    400,  300, 400-1, 300-1
     50 
     51 
     52    nLVWndWidth = (rectClient.right - PPT_LEFT_CTRL_PANEL_WIDTH - 1) / nMaxWndNumOfRow;  //(800 -0 -1) /2   = 399
     53    if (nNumOfLVWnd % nMaxWndNumOfRow == 0)
     54    {
     55           nTempNumOfLVWnd = nNumOfLVWnd;
     56           wsprintf(temp,L"nNumOfLVWnd = %d",nNumOfLVWnd);
     57             OutputDebugString(temp);
     58             //4 windows    //4%2 = 0    => nTempNumOfLVWnd = 4
     59    }
     60    else
     61       nTempNumOfLVWnd = nNumOfLVWnd + nMaxWndNumOfRow - (nNumOfLVWnd % nMaxWndNumOfRow);
     62       //1 windows    //1+2 -(1%2) = 2
     63       //9 windows    //9+3 -(9%3) = 3
     64 
     65    wsprintf(temp,L"hejie rectClient.bottom=%d,  nTempNumOfLVWnd=%d",rectClient.bottom,nTempNumOfLVWnd);
     66     OutputDebugString(temp);
     67 
     68    nLVWndHeight = (rectClient.bottom - PPT_BOTTOM_CTRL_PANEL_HEIGHT - 1) / (nTempNumOfLVWnd / nMaxWndNumOfRow);
     69    // (600-0-1)/   (2/2) => 599
     70    // (600-0-1)/   (2/2) => 599
     71    // (600-0-1)/   (4/2) => 299
     72    // (600-0-1)/   (4/2) => 299
     73    // (600-0-1)/   (9/3) => 199.6
     74 
     75     wsprintf(temp,L"hejie nLVWndHeight=%d",nLVWndHeight);
     76     OutputDebugString(temp);
     77 
     78    OutputDebugString(L"Deploy the windows of live view========");
     79    // Deploy the windows of live view
     80    for (i = 0; i < MAX_LIVE_VIEW_WINDOWS; i++) 
     81    {
     82       if (i < nNumOfLVWnd) {
     83 
     84           OutputDebugString(L"before InvalidateRect");
     85          m_pLVWnd[i]->InvalidateRect(NULL, FALSE);//redraw the rectangle
     86          nRow = i / nMaxWndNumOfRow;   //0++ / 2 =>  0  0.5  1  1.5
     87          nCol = i % nMaxWndNumOfRow;   //0++ % 2 =>  0  1    0  0 
     88          // Calculate the coordinates and size for each live view window
     89            nNextX = PPT_LEFT_CTRL_PANEL_WIDTH + (nCol * nLVWndWidth) + 1;
     90            nNextY = (nRow * nLVWndHeight) + 1;
     91 
     92            wsprintf(temp,L"hejie nNextX=%d,  nNextY=%d================",nNextX,nNextY);
     93            OutputDebugString(temp);
     94 
     95            if (rectClient.right - (nNextX + nLVWndWidth) < nLVWndWidth)
     96               nNextWidth = rectClient.right - nNextX - 1;
     97            else
     98                nNextWidth = nLVWndWidth;
     99          if ((rectClient.bottom - PPT_BOTTOM_CTRL_PANEL_HEIGHT) - (nNextY + nLVWndHeight) < nLVWndHeight)
    100               nNextHeight = (rectClient.bottom - PPT_BOTTOM_CTRL_PANEL_HEIGHT) - nNextY - 1;
    101          else
    102             nNextHeight = nLVWndHeight;
    103 
    104           wsprintf(temp,L"moveWindows 第%d个子窗口 的 nNextX=%d,  nNextY=%d,  nNextWidth=%d, nNextHeight=%d ",i,nNextX,nNextY,nNextWidth,nNextHeight);
    105           OutputDebugString(temp);
    106           
    107           
    108           //让LiveViewWnd窗口小一点, 每个窗口中间的分隔大一点。offset值-2为了缩放窗口, 让给显示选中矩形框
    109           m_pLVWnd[i]->MoveLVWindow(nNextX +2, nNextY +2, nNextWidth -2, nNextHeight-2);//modify the windwos Count!!!!!important    设置默认小窗口的size
    110           m_pLVWnd[i]->ShowWindow(SW_SHOW);
    111          
    112 
    113           //保留每个liveView Wnd的rect
    114         if(LV_WND_4 == nTotalWnd ) 
    115         {
    116             SubLiveViewRect4[i] = CRect( nNextX +1, nNextY+1, nNextWidth + nNextX+2,  nNextHeight + nNextY+2);
    117 
    118             //left和top + 1是因为不和LiveView重合
    119             //right 和bottom +2 是因为 前面offset已经+1了,然后需要再+1么?
    120         }
    121         else if(LV_WND_9 == nTotalWnd ) 
    122         {
    123             /*
    124             #ifdef _AFX_NO_OCC_SUPPORT 
    125             _AFXWIN_INLINE void CWnd::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint)
    126                 { ASSERT(::IsWindow(m_hWnd)); ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint); }
    127             #endif //_AFX_NO_OCC_SUPPORT
    128             _AFXWIN_INLINE void CWnd::MoveWindow(LPCRECT lpRect, BOOL bRepaint)
    129                 { MoveWindow(lpRect->left, lpRect->top, lpRect->right - lpRect->left,
    130                     lpRect->bottom - lpRect->top, bRepaint); }
    131             */
    132             //我们可以知道x,y, nWidth,nHeight  如何通过rect得到,
    133             //lpRect->left, lpRect->top, 
    134             //lpRect->right - lpRect->left,     //3-1
    135             //lpRect->bottom - lpRect->top,     //4-2 
    136             //上面是MoveWinodws()的X,Y,Width,Height 值。    请看上面是MoveWindows()的定义
    137 
    138 
    139 
    140             //反过来,要换算成rect值,
    141             //只需要nNextX , nNextY, nNextHeight + nNextX, nNextWidth + nNextY
    142             
    143 
    144             SubLiveViewRect9[i] = CRect( nNextX +1 , nNextY +1, nNextWidth + nNextX+2 ,  nNextHeight + nNextY+2 );
    145 
    146              
    147         }
    148 
    149 
    150       }
    151       else {
    152          m_pLVWnd[i]->InvalidateRect(NULL, FALSE);
    153          m_pLVWnd[i]->ShowWindow(SW_HIDE);
    154       }
    155    }
    156 }
    平均分隔多个窗口

     重点是:MoveWindow(x,y, width, height)要换算成Rect矩形,废了蛮多周折,才找到原因。 所以才会想起写下此篇文章。

    我们的需求是这样的,

    平均分隔各个视图后,

    用户单击/双击 后,需要有选中矩形(单击/双击 选中后,可以操作此视图对象+数据对象;  双击 全屏放大    )

    刷新如何不让丢失呢?在mainDialog的OnPaint()中,先判断nChooseIndex的值,这个值在subView中的单机事件中得到。

    然后根据我们分隔画面的保存 CRect[i]来保存每个SubView的Rectangle,

    然后就可在OnPaint()中画选中的矩形了

     1 void CMainDialog::OnPaint()
     2 {
     3     CPaintDC dc(this); // device context for painting
     4     // TODO: 在此处添加消息处理程序代码
     5     // 不为绘图消息调用 CDialog::OnPaint()
     6     
     7         //选中矩形,若单窗口模式下,则不画选中矩形
     8         if ( nTotalWnd != 1 )
     9         {
    10             //draw rectangle
    11             dc.SelectStockObject(NULL_BRUSH); //不使用画刷
    12             CPen penBlack;
    13             COLORREF crColor = ((COLORREF)(((255)|((WORD)((0))<<8))|(((DWORD)(0))<<16)));
    14             penBlack.CreatePen(PS_SOLID, 2, crColor);//penBlack.CreatePen(PS_SOLID, 3, #ff0000);
    15             CPen* pOldPen = dc.SelectObject(&penBlack);
    16 
    17             
    18 
    19             if (LV_WND_4 == nTotalWnd)
    20             {
    21             dc.Rectangle(&SubLiveViewRect4[nChooseWnd]);
    22             }
    23             
    24             if (LV_WND_9 == nTotalWnd)
    25             {
    26             dc.Rectangle(&SubLiveViewRect9[nChooseWnd]);
    27             }
    28 
    29         }
    30 }
    OnPaint

    4、画矩形还有很多种方法

                //方法1.  实心矩形,和第4个方法是一样的,一个是实心,一个是空心
                CPen penBlack;
                penBlack.CreatePen(PS_TYPE_MASK, 3, #0000ff);
                m_pDC->SelectObject(&penBlack);
                m_pDC->Rectangle(&WndRect);
                penBlack.DeleteObject();
                
                //方法2.直接画线段,可以设置线的粗细,颜色  ,这个最好,但是麻烦点。
                CPen penBlack;
                penBlack.CreatePen(PS_SOLID, 3, #000000);
                m_pDC->SelectObject(&penBlack);
                m_pDC->MoveTo(WndRect.left -3, WndRect.top);
                m_pDC->LineTo(WndRect.left -3, WndRect.bottom -3  );
                m_pDC->LineTo(WndRect.right , WndRect.bottom  );
                m_pDC->LineTo(WndRect.right , WndRect.top );
                m_pDC->LineTo(WndRect.left -3, WndRect.top -3 );
                penBlack.DeleteObject();

                //方法3 .  空心,但是没有办法设置线的粗细
                CBrush brushBlue(#000000);
                dc.FrameRect(&WndRect,&brushBlue);

        

        //方法4 . 空心,可设置线的粗细,颜色

        CClientDC dc(this);   //获取设备句柄
                dc.SelectStockObject(NULL_BRUSH); //不使用画刷
                CPen penBlack;
                penBlack.CreatePen(PS_SOLID, 3, #ff0000);
                CPen* pOldPen = dc.SelectObject(&penBlack);
                //pOldPen->DeleteObject(); //大家可以试下DeleteObject penBlack和pOldPen 有什么区别
                //dc.Rectangle(CRect(WndRect.left -2,WndRect.top -2, WndRect.right+1,WndRect.bottom+1));
      

        //方法5  不能设置线的粗细,d3d不懂,如果错了,欢迎大家纠正,共同提高嘛,  不过朋友叫我速度学openGL ,他们那做游戏,如果想赚点钱,可以试试吧。

        //pDC->Draw3dRect(&WndRect,#ff0000,#00ff00);

    5.双击全屏,再双击还原

    我试过很多方法,最简单的就是MoveWindows,但是全屏后能还原小窗口的都不满意,

    我就介绍一种完美的解决方案吧。

     1 void CLiveViewWnd::OnLButtonDblClk(UINT nFlags, CPoint point)
     2 {
     3     // TODO: 在此添加消息处理程序代码和/或调用默认值
     4     CMainDialog* mainDialog = NULL;
     5     mainDialog = (CMainDialog*) GetParent();
     6     mainDialog->nChooseWnd = m_ucWndNo;
     7 
     8     CStatic::OnLButtonDblClk(nFlags, point);
     9     OutputDebugString(L"enter =====================CLiveViewWnd::OnLButtonDblClk");
    10     
    11 
    12     m_bFullScreen=!m_bFullScreen; // 设置全屏显示标志
    13     LONG style = ::GetWindowLong(this->m_hWnd,GWL_STYLE);
    14 
    15     if(m_bFullScreen)//全屏显示
    16     {
    17      /*   //用MFC隐藏系统任务栏
    18         CWnd * wnd = FindWindow(L"Shell_TrayWnd",NULL);
    19         wnd->SetWindowPos(NULL,0,0,0,0,SWP_HIDEWINDOW);
    20         */
    21         
    22         m_hWndParent=::GetParent(m_hWnd);   
    23         ::ShowWindow(m_hWndParent,SW_HIDE); 
    24 
    25         ::SetParent(m_hWnd,NULL);   
    26         style &= ~(WS_DLGFRAME | WS_THICKFRAME);
    27         
    28         SetWindowLong(this->m_hWnd,NULL, style);//SetWindowLong(this->m_hWnd,GWL_STYLE, style); GWL_STYLE表示MFC窗口属性,NULL表示没有窗口属性。
    29         this->ShowWindow(SW_SHOWMAXIMIZED);//this->ShowWindow(SHOW_FULLSCREEN);
    30 
    31         //CRect rect;
    32         //this->GetWindowRect(&rect);
    33         //::SetWindowPos((this->m_hWnd,HWND_NOTOPMOST,rect.left-1, rect.top-1, rect.right-rect.left + 3, rect.bottom-rect.top + 3, SWP_FRAMECHANGED);
    34  
    35         int   nScreenWidth=GetSystemMetrics(SM_CXSCREEN);   
    36         int   nScreenHeight=GetSystemMetrics(SM_CYSCREEN);
    37         ::SetWindowPos(this->m_hWnd,HWND_TOPMOST,0,0, nScreenWidth,nScreenHeight, SWP_FRAMECHANGED);
    38     }
    39     else
    40     {
    41        /* //用MFC显示系统任务栏
    42         CWnd * wnd = FindWindow(L"Shell_TrayWnd",NULL);
    43         wnd->SetWindowPos(NULL,0,0,0,0,SWP_SHOWWINDOW);
    44         //this->SetWindowPos(NULL,0,0,0,0,SWP_SHOWWINDOW);
    45         */
    46 
    47         style |= WS_DLGFRAME | WS_THICKFRAME;
    48         SetWindowLong(this->m_hWnd, NULL, style);
    49         ::SetParent(m_hWnd,m_hWndParent);   
    50         ::ShowWindow(m_hWndParent,SW_SHOW);  
    51     }
    52 }
    OnLButtonDblClk

    需要注意的是

    SetWindowLong(this->m_hWnd,GWL_STYLE, style);   // GWL_STYLE表示MFC窗口属性,NULL表示没有窗口属性。

    SetWindowPos(this->m_hWnd,HWND_TOPMOST,0,0, nScreenWidth,nScreenHeight, SWP_FRAMECHANGED);  //HWND_TOPMOST  显示优先级为最高层

  • 相关阅读:
    摄像机模型 (Camera Model)
    TP中如何用IF
    Mysql连接报错:1130-host ... is not allowed to connect to this MySql server如何处理
    LNMP环境源码搭建
    Linux之不得不说的init(Linux启动级别的含义 init 0-6)
    PHP 生成毫秒时间戳
    Linux Bash Shell字符串截取
    Linux crontab任务调度
    下载百度文库文档
    关于java socket中的read方法阻塞问题
  • 原文地址:https://www.cnblogs.com/scotth/p/3424978.html
Copyright © 2011-2022 走看看