精通 VC++ 实效编程280例 - 01 窗口

    添加时间:2013-6-11 点击量:

    窗口是屏幕上的一个矩形区域。窗口分为3种:重叠窗口、弹出窗口和子窗口。每个窗口都有由体系绘制的“非客户区”和应用法度绘制的“客户区”。在 MFC 中,CWnd 类为各类窗口供给了基类。


    1 经由过程 HWND 获得 CWnd 指针


    经由过程 HWND 获得 Cwnd 指针可以调用 Cwnd::FromHandle 函数。



    void CDemoDlg::OnButton1() 
    
    {
    HWND hWnd = GetSafeHwnd(); //获合适前窗口的句柄
    CWnd pWnd = CWnd::FromHandle(hWnd); //经由过程HWND获得CWnd指针
    CString strText = _T();
    strText.Format(pWnd=0 x%X\nthis=0 x%X\n,pWnd,this);
    AfxMessageBox(strText);
    }




    2 获得应用法度主窗口的指针


    主窗口指针保存在 CWinThread::m_pMainWnd 中。可以起首调用 AfxGetApp 函数获得应用法度的指针,然后经由过程应用法度指针获得主窗口的指针。



    void CDemoDlg::OnButton2() 
    
    {
    CDemoApp pApp = (CDemoApp)AfxGetApp(); //获得应用法度指针
    CWnd pMainWnd = pApp->m_pMainWnd; //获得主窗口指针
    CString strText = _T();
    strText.Format(pMainWnd=0 x%X\nthis=0 x%X\n,pMainWnd,this);
    AfxMessageBox(strText);
    }




    3 获得指定点的窗口


    获得指定点的窗口可以调用 CWnd::WindowFromPoint 函数。


    a 在 CDemoDlg 类中重载 CWnd::PreTranslateMessage 函数。



    BOOL CDemoDlg::PreTranslateMessage(MSG pMsg) 
    
    {
    if (pMsg->message == WM_MOUSEMOVE)
    {
    CPoint point(LOWORD(pMsg->lParam),HIWORD(pMsg->lParam));
    ::ClientToScreen(pMsg->hwnd, &point); //客户区坐标转换为屏幕坐标
    OnMouseMove(0,point);
    }
    return CDialog::PreTranslateMessage(pMsg);
    }


    b 在 CDemoDlg 类中添加 WM_MOUSEMOVE 消息处理惩罚函数。



    void CDemoDlg::OnMouseMove(UINT nFlags, CPoint point) 
    
    {
    CWnd pWnd = WindowFromPoint(point); //获得指定点的窗口
    if (pWnd != NULL)
    {
    TRACE(%d\n,pWnd);
    if (IsChild(pWnd))
    {
    CString strText = _T();
    pWnd->GetWindowText(strText);
    SetWindowText(strText);
    }
    }
    CDialog::OnMouseMove(nFlags, point);
    }




    4 有效和最小化窗口


    有效和最小化窗口可以调用 CWnd::SendMessage 函数发送有效或最小化窗口消息。


    LRESULT SendMessage( 


    UINT message,    //发送的消息,值为 WM_SYSCOMMAND 时默示体系号令消息。 


    WPARAM wParam = 0,     //当 message 值为 WM_SYSCMMAND,参数 wParam 值为 SC_MAXIMIZE、SC_MINIMIZE、


    LPARAM lParam = 0 );      //SC_RESTORE 时分别默示有效窗口、最小化窗口、恢复窗口。



    void CDemoDlg::OnButton3() 
    
    {
    //有效窗口
    SendMessage(WM_SYSCOMMAND,SC_MAXIMIZE,0);
    }

    void CDemoDlg::OnButton4()
    {
    //最小化窗口
    SendMessage(WM_SYSCOMMAND,SC_MINIMIZE,0);
    }

    void CDemoDlg::OnButton5()
    {
    //恢复窗口
    SendMessage(WM_SYSCOMMAND,SC_RESTORE,0);
    }




    5 封闭窗口


    封闭窗口可以调用 CWnd::SendMessage 函数发送 WM_CLOSE 消息。框架将调用 CWnd::OnClose 函数处理惩罚 WM_CLOSE 消息。默认景象下,OnClose 函数将调用 CWnd::DestroyWindow 函数封闭窗口。



    void CDemoDlg::OnButton6() 
    
    {
    //封闭窗口
    SendMessage(WM_CLOSE,0,0);
    }

    void CDemoDlg::OnClose() //添加 WM_CLOSE 消息处理惩罚函数
    {
    //断定是否封闭
    if (IDYES == MessageBox(_T(是否封闭窗口?),NULL,MB_YESNO))
    {
    CDialog::OnClose();
    }
    }




    6 设置窗口的大小和地位


    设置窗口大小和地位可经由过程两种办法:1.调用 CWnd::SetWindowPos 函数;2.调用 CWnd::MoveWindow 函数。



    void CDemoDlg::OnButton7() 
    
    {
    //设置窗口的大小和地位
    SetWindowPos(NULL,0,0,320,200,SWP_NOZORDER);
    }

    void CDemoDlg::OnButton8()
    {
    //设置窗口的大小和地位
    MoveWindow(0,200,200,320);
    } 




    7 居中显示窗口


    使窗口居中显示可以调用 CWnd::CenterWindow 函数。



    void CDemoDlg::OnButton9() 
    
    {
    //居中显示窗口
    CenterWindow();
    } 




    8 顶层显示窗口


    使窗口顶层显示,可以调用 CWnd::SetWindowPos 函数,设置对话框窗口的层次为最顶层。



    void CDemoDlg::OnButton10() 
    
    {
    //设置窗口层次
    SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE); //SWP_NOSIZE:默示窗口对峙当前的大小,SWP_NOMOVE:默示窗口对峙当前的地位
    }




    9 设置窗口图标


    起首调用 CWinApp::LoadIcon 函数加载图标资料,然后调用 CWnd::SetIcon 函数设置图标。



    void CDemoDlg::OnButton11() 
    
    {
    //加载图标
    HICON hIcon = AfxGetApp()->LoadIcon(IDI_ICON);
    //设置图标
    SetIcon(hIcon,FALSE); //FALSE:设置法度小图标,TRUE:设置任务栏大图标
    } 




    10 获得和设置窗口的题目


    获得和设置窗口题目可以分别调用 CWnd::GetWindowText 和 CWnd::SetWindowText 函数。



    void CDemoDlg::OnButton12() 
    
    {
    CString strText = _T();
    GetWindowText(strText); //获得窗口题目
    SetDlgItemText(IDC_TEXT,strText); //设置编辑框文本
    }

    void CDemoDlg::OnButton13()
    {
    CString strText = _T();
    GetDlgItemText(IDC_TEXT,strText); //获得编辑框文本
    SetWindowText(strText); //设置窗口题目
    }




    11 显示或隐蔽窗口的题目栏


    显示或隐蔽窗口的题目栏可以调用 CWnd::ModifyStyle 函数。



    void CDemoDlg::OnButton14() 
    
    {
    //删除题目栏风格
    ModifyStyle(WS_CAPTION,0,SWP_FRAMECHANGED);
    }

    void CDemoDlg::OnButton15()
    {
    //添加题目栏风格
    ModifyStyle(0,WS_CAPTION,SWP_FRAMECHANGED);
    }




    12 改变窗口外形


    标准窗口的外形是矩形的。改变窗口的外形起首调用 CRgn 类的成员函数创建响应外形的区域,然后调用 CWnd::SetWindowRgn 函数将其设置为窗口区域。


    CRgn 类的 CreateRectRgn、CreateEllipticRgn、CreatePolygonRgn 和 CreateRoundRectRgn 函数可以分别用来创建矩形、卵形、多边形和圆矩形区域。 



    void CDemoDlg::OnButton16() 
    
    {
    CRect rect;
    GetClientRect(rect);
    //创建矩形区域
    CRgn rgn;
    rgn.CreateRectRgn(rect.left,rect.top,rect.right,rect.bottom);
    //设置窗口的区域
    SetWindowRgn((HRGN)rgn,TRUE);
    }

    void CDemoDlg::OnButton17()
    {
    CRect rect;
    GetClientRect(rect);
    //创建卵形区域
    CRgn rgn;
    rgn.CreateEllipticRgn(0,0,rect.Width(),rect.Height());
    //设置窗口的区域
    SetWindowRgn((HRGN)rgn,TRUE);
    }

    void CDemoDlg::OnButton18()
    {
    CRect rect;
    GetClientRect(rect);
    CPoint point[6];
    point[0].x = 0;
    point[0].y = rect.Height() / 2;
    point[1].x = rect.Width() / 3;
    point[1].y = 0;
    point[2].x = 2 rect.Width() / 3;
    point[2].y = 0;
    point[3].x = rect.Width();
    point[3].y = rect.Height() / 2;
    point[4].x = 2 rect.Width() / 3;
    point[4].y = rect.Height();
    point[5].x = rect.Width() / 3;
    point[5].y = rect.Height();
    //创建多边形区域
    CRgn rgn;
    rgn.CreatePolygonRgn(point,6,ALTERNATE);
    //设置窗口的区域
    SetWindowRgn((HRGN)rgn,TRUE);
    }

    void CDemoDlg::OnButton19()
    {
    CRect rect;
    GetClientRect(rect);
    //创建圆矩形区域
    CRgn rgn;
    rgn.CreateRoundRectRgn(0,0,rect.Width(),rect.Height(),rect.Width() / 2,rect.Height() / 2);
    //设置窗口的区域
    SetWindowRgn((HRGN)rgn,TRUE);
    }




    13 设置窗口的透明区域


    设置窗口的透明区域,起首调用 CRgn::CreateRectRgn 创建一个区域,然后调用 CRgn::CombineRgn 函数将须要透明的区域去掉,最后调用 CWnd::SetWindowRgn 函数将其设置为窗口区域。



    void CDemoDlg::OnButton20() 
    
    {
    CRect rect1;
    GetWindowRect(rect1);
    CRect rect2;
    GetClientRect(rect2);
    ClientToScreen(rect2);
    CRgn rgn1;
    rgn1.CreateRectRgn(rect1.left,rect1.top,rect1.right,rect1.bottom);
    CRgn rgn2;
    rgn2.CreateRectRgn(rect2.left,rect2.top,rect2.right,rect2.bottom);
    CRgn rgn;
    rgn.CreateRectRgn(0,0,1,1);
    rgn.CombineRgn(&rgn1,&rgn2,RGN_DIFF);
    //设置窗口区域
    SetWindowRgn((HRGN)rgn,TRUE);
    }




    14 透明窗口


    实现透明窗口,起首调用 CWnd::ModifyStyleEx 函数,添加窗口的 WS_EX_LAYERED(0 x00080000) 扩大风格,然后调用 SDK 的 SetLayeredWindowAttributes 函数设置窗口的透明度和透明色。



    void CDemoDlg::OnButton21() 
    
    {
    //添加 WS_EX_LAYERED(0 x80000) 扩大风格
    ModifyStyleEx(0,0 x80000);
    //加载 User32.DLL 动态链接库
    HMODULE hModule = LoadLibrary(User32.DLL);
    if (hModule != NULL)
    {
    typedef BOOL (WINAPI FUNC)(HWND,COLORREF,BYTE,DWORD);
    //获得 SetLayeredWindowAttributes 函数指针
    FUNC func = (FUNC)GetProcAddress(hModule,SetLayeredWindowAttributes);
    if (func != NULL)
    {
    func(GetSafeHwnd(),0,128,2);
    }
    FreeLibrary(hModule);
    }
    }




    15 窗口闪烁


    使窗口闪烁可以调用 CWnd::FlashWindow 函数。



    void CDemoDlg::OnButton22() 
    
    {
    //设置按时器
    SetTimer(1,1000,NULL);
    }

    void CDemoDlg::OnButton23()
    {
    //封闭按时器
    KillTimer(1);
    //窗口返回原始状况
    FlashWindow(FALSE);
    }

    void CDemoDlg::OnTimer(UINT nIDEvent)
    {
    if (nIDEvent == 1)
    {
    //窗口从一种状况闪烁到另一种状况
    FlashWindow(TRUE);
    }
    CDialog::OnTimer(nIDEvent);
    }




    16 窗口


    实现窗口,起首调用 CRgn::CreateRectRgn 和 CRgn::CombineRgn 函数创建并归并多个区域,然后调用 CWnd::SetWindowRgn 函数将其设置为窗口区域。


    VC对话框如何添加WM_ERASEBKGND消息(OnEraseBkgnd函数):


    http://guohaiyang.blog.163.com/blog/static/3213403720081027104147/



    void CDemoDlg::OnButton24() 
    
    {
    CRect rect;
    GetWindowRect(&rect);
    //加载位图
    CBitmap bmp;
    bmp.LoadBitmap(IDB_BITMAP);
    //将位图选入设备景象
    CDC dc;
    CDC pDC = GetDC();
    dc.CreateCompatibleDC(pDC);
    dc.SelectObject(&bmp);
    //将位图中黑色区域变成透明区域
    CRgn rgn1;
    rgn1.CreateRectRgn(0,0,rect.Width(),rect.Height());
    for (int x = 0;x < rect.Width();x++)
    {
    for (int y = 0;y < rect.Height();y++)
    {
    COLORREF cr = dc.GetPixel(x,y);
    if (cr == RGB(0,0,0))
    {
    CRgn rgn2;
    rgn2.CreateRectRgn(x,y,x+1,y+1);
    rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR);
    }
    }
    }
    //设置窗口区域
    SetWindowRgn((HRGN)rgn1,TRUE);
    ReleaseDC(pDC);
    }
    //添加 WM_ERASEBKGND 消息处理惩罚函数
    BOOL CDemoDlg::OnEraseBkgnd(CDC pDC)
    {
    CRect rect;
    GetWindowRect(&rect);
    CBitmap bmp;
    bmp.LoadBitmap(IDB_BITMAP);
    CDC dc;
    dc.CreateCompatibleDC(pDC);
    dc.SelectObject(&bmp);
    pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);
    return TRUE;
    }




    17 动画窗口


    实现动画窗口,可以调用 SDK 的 AnimateWindow 函数。



    BOOL CDemoDlg::OnInitDialog()
    
    {
    CDialog::OnInitDialog();
    // ...
    //窗口居中
    CenterWindow();
    //显示动画窗口
    AnimateWindow(GetSafeHwnd(), 3000, AW_BLEND);
    return TRUE;
    }




    18 桌面窗口


    获得桌面窗口,可以调用 CWnd::GetDesktopWindow 函数。



    void CDemoDlg::OnButton25() 
    
    {
    //获得桌面窗口
    CWnd pWnd = CWnd::GetDesktopWindow();
    //获得窗口大小
    CRect rect;
    pWnd->GetClientRect(rect);
    CString strText = _T();
    strText.Format(_T(桌面窗口大小:%dX%d),rect.Width(),rect.Height());
    AfxMessageBox(strText);
    }




    19 最小化桌面所有窗口


    Window 中可以哄骗快捷键 Win+M 最小化所有窗口。是以,可以经由过程向任务栏窗口发送 ID 为 0 x1F5(Win+M) 的 WM_HOTKEY 消息,使桌面所有窗口最小化。起首调用 CWnd::FindWindow 函数获得窗口,然后调用 CWnd::SendMessage 函数向窗口发送消息。



    void CDemoDlg::OnButton26() 
    
    {
    //获得任务栏窗口
    CWnd pWnd = CWnd::FindWindow(_T(Shell_TrayWnd),NULL);
    //发送ID为0 x1F5(Win+M)的WM_HOTKEY消息
    pWnd->SendMessage(WM_HOTKEY,0 x1F5);
    }




    20 获取任务栏窗口


    获得任务栏窗口,可以调用 CWnd::FindWinow 函数。



    void CDemoDlg::OnButton27() 
    
    {
    //获得任务栏窗口
    CWnd pWnd = CWnd::FindWindow(_T(Shell_TrayWnd),NULL);
    //获得窗口大小
    CRect rect;
    pWnd->GetClientRect(rect);
    CString strText = _T();
    strText.Format(_T(任务栏窗口大小:%dX%d),rect.Width(),rect.Height());
    AfxMessageBox(strText);
    }




    21 显示或隐蔽任务栏


    显示或隐蔽任务栏,起首调用 CWnd::FindWindow 函数获得窗口,然后调用 CWnd::ShowWindow 函数隐蔽或显示窗口。 



    void CDemoDlg::OnButton28() 
    
    {
    //获得任务栏窗口
    CWnd pWnd = CWnd::FindWindow(_T(Shell_TrayWnd),NULL);
    //隐蔽窗口
    if (pWnd->IsWindowVisible())
    {
    pWnd->ShowWindow(SW_HIDE);
    }
    }

    void CDemoDlg::OnButton29()
    {
    //获得任务栏窗口
    CWnd pWnd = CWnd::FindWindow(_T(Shell_TrayWnd),NULL);
    //显示窗口
    if (!pWnd->IsWindowVisible())
    {
    pWnd->ShowWindow(SW_SHOW);
    }

    }




    22 列举桌面所有顶层窗口



    BOOL CDemoDlg::OnInitDialog()
    
    {
    CDialog::OnInitDialog();
    // ...
    //初始化列表框控件
    CListCtrl pList = (CListCtrl)GetDlgItem(IDC_LIST);
    pList->ModifyStyle(LVS_ICON | LVS_SMALLICON | LVS_LIST,LVS_REPORT);
    pList->SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
    pList->InsertColumn(0,_T(窗口类名),LVCFMT_LEFT,115);
    pList->InsertColumn(1,_T(窗口题目),LVCFMT_LEFT,150);
    return TRUE;
    }


    列举桌面所有顶层窗口有以下两种办法:


    a 调用 CWnd::GetDesktopWindow 和 CWnd::GetWindow 函数:起首调用 CWnd::GetDesktopWindow 函数,获得桌面窗口,然后调用 CWnd::GetWindow 函数,列举所有子窗口。



    void CDemoDlg::OnButton30() 
    
    {
    CListCtrl pList = (CListCtrl)GetDlgItem(IDC_LIST);
    pList->DeleteAllItems();
    pList->SetRedraw(FALSE);
    //获得桌面窗口
    CWnd pDesktopWnd = CWnd::GetDesktopWindow();
    //获得第一个子窗口
    CWnd pWnd = pDesktopWnd->GetWindow(GW_CHILD);
    while(pWnd != NULL)
    {
    int nItem = pList->GetItemCount();
    //获得窗口类名
    CString strClassName = _T();
    ::GetClassName(pWnd->GetSafeHwnd(),strClassName.GetBuffer(256),256);
    strClassName.ReleaseBuffer();
    pList->InsertItem(nItem,strClassName);
    //获得窗口题目
    CString strWindowText = _T();
    ::GetWindowText(pWnd->GetSafeHwnd(),strWindowText.GetBuffer(256),256);
    strWindowText.ReleaseBuffer();
    pList->SetItemText(nItem,1,strWindowText);
    //持续获得下一个子窗口
    pWnd = pWnd->GetWindow(GW_HWNDNEXT);
    }
    pList->SetRedraw(TRUE);
    }


    b 调用 SDK 的 EnumWindows 函数。



    //添加全局函数
    
    BOOL CALLBACK EnumWndPorc(HWND hWnd,LPARAM lParam)
    {
    if (hWnd == NULL)
    {
    return FALSE;
    }
    CListCtrl pList = (CListCtrl)lParam;
    int nItem = pList->GetItemCount();
    //获得窗口类名
    CString strClassName = _T();
    ::GetClassName(hWnd,strClassName.GetBuffer(256),256);
    strClassName.ReleaseBuffer();
    pList->InsertItem(nItem,strClassName);
    //获得窗口题目
    CString strWindowText = _T();
    ::GetWindowText(hWnd,strWindowText.GetBuffer(256),256);
    strWindowText.ReleaseBuffer();
    pList->SetItemText(nItem,1,strWindowText);
    return TRUE;
    }

    void CDemoDlg::OnButton31()
    {
    CListCtrl pList = (CListCtrl)GetDlgItem(IDC_LIST);
    pList->DeleteAllItems();
    pList->SetRedraw(FALSE);
    //列举窗口
    ::EnumWindows(EnumWndPorc,(LPARAM)pList);
    pList->SetRedraw(TRUE);
    }


      

    无论对感情还是对生活,“只要甜不要苦”都是任性而孩子气的,因为我们也不完美,我们也会伤害人。正因为我们都不完美,也因为生活从不是事事如意,所以对这些“瑕疵”的收纳才让我们对生活、对他人的爱变得日益真实而具体。—— 汪冰《世界再亏欠你,也要敢于拥抱幸福》
    分享到: